Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

Мы можем также использовать выражение

extern "C"
, чтобы вызвать функцию языка С++ из программы, написанной на языке С.

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

extern "C" int call_f(S* p, int i)

{

return p–>f(i);

}

Теперь в программе на языке 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++. Однако эта стратегия серьезно ограничивает возможности использования языка С++, поэтому мы ее не рекомендуем.

27.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
), добавляя новый раздел case в инструкцию
switch
.

Вторая проблема носит довольно неприятный характер, поскольку мы не можем включить псевдовиртуальные функции ни в какие библиотеки, так как наши пользователи должны будут довольно часто модифицировать эти функции. Наиболее эффективной альтернативой является использование указателей на функции.

typedef void (*Pfct0)(struct Shape2*);

typedef void (*Pfct1int)(struct Shape2*,int);

struct Shape2 {

  • Читать дальше
  • 1
  • ...
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: