Теперь в программе на языке C можно косвенно вызвать функцию-член f().

/* вызов функции на языке C++ из функции на языке C: */

int call_f(S* p, int i);

struct S* make_S(int,const char*);

void my_c_fct(int i)

{

  /* ... */

  struct S* p = make_S(x, "foo");

  int x = call_f(p,i);

  /* ... */

}

Для того чтобы эта конструкция работала, больше о языке С++ упоминать не обязательно.

Выгоды такого взаимодействия очевидны: код можно писать на смеси языков C и C++. В частности, программы на языке C++ могут использовать библиотеки, написанные на языке C, а программы на языке C могут использовать библиотеки, написанные на языке С++. Более того, большинство языков (особенно Fortran) имеют интерфейс вызова функций, написанных на языке С, и допускают вызов своих функций в программах, написанных на языке С.

В приведенных выше примерах мы предполагали, что программы, написанные на языках C и C++, совместно используют объект, на который ссылается указатель p. Это условие выполняется для большинства объектов. В частности, допустим, что у нас есть следующий класс:

// В языке C++:

class complex {

  double re, im;

public:

  // все обычные операции

};

Тогда можете не передавать указатель на объект в программу, написанную на языке С, и наоборот. Можете даже получить доступ к членам re и im в программе, написанной на языке C, с помощью объявления

/* В языке C: */

struct complex {

  double re, im;

  /* никаких операций */

};

  Правила компоновки в любом языке могут быть сложными, а правила компоновки модулей, написанных на нескольких языках, иногда даже трудно описать. Тем не менее функции, написанные на языках C и C++, могут обмениваться объектами встроенных типов и классами (структурами) без виртуальных функций. Если класс содержит виртуальные функции, можете просто передать указатели на его объекты и предоставить работу с ними коду, написанному на языке C++. Примером этого правила является функция call_f(): функция f() может быть virtual. Следовательно, этот пример иллюстрирует вызов виртуальной функции из программы, написанной на языке C.

Кроме встроенных типов, простейшим и наиболее безопасным способом совместного использования типов является конструкция struct, определенная в общем заголовочном файле языков C и C++. Однако эта стратегия серьезно ограничивает возможности использования языка С++, поэтому мы ее не рекомендуем. 

<p id="AutBody_Root541"><strong>27.2.5. Указатели на функции</strong></p>

Что можно сделать на языке С, если мы хотим использовать объектно-ориентированную технологию (см. разделы 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()), добавляя новый раздел case в инструкцию 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);

}

Структуру Shape2 можно использовать точно так же, как структуру Shape1.

int f(struct Shape2* pp)

{

  draw(pp);

  /* ... */

}

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже