Когда плюсистов насильно пересаживают на Си, одним из пунктов ломки по нормальным языкам является отсутствие адекватных объектов и их методов. Но если становится совсем плохо, методы можно легко реализовать.
Пусть дана структура, точка, например. Она состоит из 2 координат:
Функция изменения координат будет выглядеть так:
Но можно применить C++ ситль и тогда у объектов внезапно появятся методы:
Как видим, теперь одну и ту же функцию можно вызывать просто так, а можно как метод объекта. Вообще, второе на мой взгляд довольно сомнительная практика.
Из плюсов у неё только то, что можно меньше заботиться о пространстве имён (часто для решения этой проблемы в Си используется префикс типа point_MoveBy).
Из минусов - лишний геморрой с указателями на функции, увеличивается размер объектов, на вызов метода из одного объекта можно подать другой объект, что приведёт к путанице.
В общем это приём, который добавляет проблем, не внося никаких плюсов.
UPD: самый существенный минус - осложнения с оптимизацией. Об этом здесь.
Пусть дана структура, точка, например. Она состоит из 2 координат:
typedef {
float x;
float y;
} Point;
Функция изменения координат будет выглядеть так:
void movePointBy(Point * p, int x, int y) {
p->x += x;
p->y += y;
}
Но можно применить C++ ситль и тогда у объектов внезапно появятся методы:
typedef struct _Point {
void (*moveBy) (struct _Point * self, int x, int y);
float x;
float y;
} Point;
void movePointBy(Point * p, int x, int y) {
p->x += x;
p->y += y;
}
int main() {
Point p;
p.moveBy = movePointBy;
movePointBy(&p, 1, 2);
p.moveBy(&p, 1, 2);
return 0;
}
Как видим, теперь одну и ту же функцию можно вызывать просто так, а можно как метод объекта. Вообще, второе на мой взгляд довольно сомнительная практика.
Из плюсов у неё только то, что можно меньше заботиться о пространстве имён (часто для решения этой проблемы в Си используется префикс типа point_MoveBy).
Из минусов - лишний геморрой с указателями на функции, увеличивается размер объектов, на вызов метода из одного объекта можно подать другой объект, что приведёт к путанице.
В общем это приём, который добавляет проблем, не внося никаких плюсов.
UPD: самый существенный минус - осложнения с оптимизацией. Об этом здесь.
Когда плюсисты возмущенно говорят о том, что в Си нет объектов - я им показываю GObject из GTK+, Pango и прочих проектов. Всё там есть, и эти ваши объекты :)
ОтветитьУдалитьЗдесь я с плюсистами согласен ) Точнее как... В Си можно эмулировать некое подобие объектов, но не в понимании плюсов. Они скорее к питону ближе.
УдалитьНа Сишных объектах у тебя не будет ни честных приватных методов, ни конструктора/деструктора. Проблемно сделать полиморфизм. Он либо будет (при этом весьма кривой), но у тебя отвалится и без того никудышная типизация Си, либо сохранияешь типизацию, но на каждый тип пишешь свой отдельный метод.
Это так, навскидку. А насчёт описанного в посте способа симуляции плюсовых методов я чуть позже напишу почему так не стоит делать в принципе.
public/privatные методы - это coding sugar, они ж для нас человеков, а не системы существуют :)
УдалитьКонструктор/деструктор можно сэмулировать вызовом вручную специальной функции.
Неявный вызов конструктора - это тоже coding sugar ))
Си вообще язык низкого уровня, на нем вполне реально и быстро сэмулировать и таблицы виртуальных функций, и преобразование типов (в том числе и RTTI), другой вопрос что Сишный код использующий эту обертку в общем виде будет выглядеть достаточно громоздко и чудовищно.
Вот, пожалуйте:
Удалитьhttp://maemo.org/api_refs/5.0/beta/gobject/howto-gobject-methods.html
здесь и
Non-virtual public methods
Virtual public methods
Virtual private Methods
> public/privatные методы - это coding sugar, они ж для нас человеков, а не системы существуют :)
УдалитьНу, плюсовый компилятор ругается, когда пытаешься обратиться к приватным членам из вне. Хотя да, в данном конкретном случае оно действительно больше для человеков.
Глобально с этой эмуляцией мне не нравятся 2 вещи:
1 - эмуляция усложняет работу компилятора. Как в плане оптимизаций, так и в плане отслеживания ошибок на стадии написания кода.
2 - если так люди так упорно пытаются использовать в языке A возможности языка B, то что мешает им сразу взять язык B и не использовать те его возможности, которые не нравятся?
> Из плюсов у неё только то, что можно меньше заботиться о пространстве имён
ОтветитьУдалитьКогда я только начал писать на С++ (один из первых моих проектов - 3D движок) я по сути продолжал писать на Си, но оборачивал всё в неймспейсы (namespace). Только потом я прочитал Страуструпа и узнал о том, что основное их назначение - это обёртка и портабельность для старого Сишного кода, во избежании конфликта имён идентификаторов.