Программирование. Принципы и практика использования C++ Исправленное издание, стр. 388
// В языке C++:class complex { double re, im;public: // все обычные операции};Тогда можете не передавать указатель на объект в программу, написанную на языке С, и наоборот. Можете даже получить доступ к членам
reim/* В языке C: */struct complex { double re, im; /* никаких операций */};
call_f()f()virtualКроме встроенных типов, простейшим и наиболее безопасным способом совместного использования типов является конструкция
struct27.2.5. Указатели на функции
Что можно сделать на языке С, если мы хотим использовать объектно-ориентированную технологию (см. разделы 14.2–14.4)? По существу, нам нужна какая-то альтернатива виртуальным функциям. Большинству людей в голову в первую очередь приходит мысль использовать структуру с “полем типа” (“type field”), описывающим, какой вид фигуры представляет данный объект. Рассмотрим пример.
struct Shape1 { enum Kind { circle, rectangle } kind; /* ... */};void draw(struct Shape1* p){ switch (p–>kind) { case circle: /* рисуем окружность */ break; case rectangle: /* рисуем прямоугольник */ break; }}int f(struct Shape1* pp){ draw(pp); /* ... */}Этот прием срабатывает. Однако есть две загвоздки.
• Для каждой псевдовиртуальной функции (такой как функция
draw()switch• Каждый раз, когда мы добавляем новую фигуру, мы должны модифицировать каждую псевдовиртуальную функцию (такую как функция
draw()switchВторая проблема носит довольно неприятный характер, поскольку мы не можем включить псевдовиртуальные функции ни в какие библиотеки, так как наши пользователи должны будут довольно часто модифицировать эти функции. Наиболее эффективной альтернативой является использование указателей на функции.
typedef void (*Pfct0)(struct Shape2*);typedef void (*Pfct1int)(struct Shape2*,int);struct Shape2 { Pfct0 draw; Pfct1int rotate; /* ... */};void draw(struct Shape2* p){ (p–>draw)(p);}void rotate(struct Shape2* p, int d){ (p–>rotate)(p,d);}Структуру
Shape2Shape1int f(struct Shape2* pp){ draw(pp); /* ... */}Проделав небольшую дополнительную работу, мы можем добиться, чтобы объекту было не обязательно хранить указатель на каждую псевдовиртуальную функцию. Вместо этого можем хранить указатель на массив указателей на функции (это очень похоже на то, как реализованы виртуальные функции в языке С++). Основная проблема при использовании таких схем в реальных программах заключается в том, чтобы правильно инициализировать все эти указатели на функции.
27.3. Второстепенные языковые различия
В этом разделе приводятся примеры незначительных различий между языками С и С++, которые могут вызвать у читателей затруднения, если они впервые о них слышат. Некоторые из них оказывают серьезное влияние на программирование, поскольку их надо явным образом учитывать.
27.3.1. Дескриптор пространства имен struct
В языке C имена структур (в нем нет ключевого слова
classstructstruct