Поскольку директива компоновки применяется ко всем функциям в объявлении, для передачи функции С++ указателя на функцию С необходимо использовать определение типа (см. раздел 2.5.1):
//
extern "С" typedef void FC(int);
//
void f2(FC *);
Используя директиву компоновки в определении функции, написанной на языке С++, эту функцию можно сделать доступной для программы, написанной на другом языке.
//
extern "С" double calc(double dparm) { /* ... */ }
Код, создаваемый компилятором для этой функции, будет соответствовать указанному языку.
Следует заметить, что типы параметров и возвращаемого значения в функциях для разных языков зачастую ограничены. Например, почти наверняка нельзя написать функцию, которая передает объекты нетривиального класса С++ программе на языке С. Программа С не будет знать о конструкторах, деструкторах или других специфических для класса операциях.
Чтобы позволить компилировать тот же файл исходного кода на языке С или С++, при компиляции на языке С++ препроцессор автоматически определяет имя __cplusplus
(два символа подчеркивания). Используя эту переменную, при компиляции на С++ можно условно включить код, компилируемый только на С++:
#ifdef __cplusplus
//
extern "С"
#endif
int strcmp(const char*, const char*);
Взаимодействие директив компоновки и перегрузки функций зависит от конкретного языка. Если язык поддерживает перегрузку функций, то компилятор, обрабатывая директивы компоновки для того языка, вероятней всего, выполнит ее.
Язык С не поддерживает перегрузку функций, поэтому нет ничего удивительного в том, что директива компоновки языка С может быть определена только для одной из функций в наборе перегруженных функций:
//
extern "С" void print(const char*);
extern "С" void print(int);
Если одна из функций в наборе перегруженных функций является функцией языка С, все остальные функции должны быть функциями С++:
class SmallInt { /* ... */ };
class BigNum { /* ... */ };
//
//
//
extern "С" double calc(double);
extern SmallInt calc(const SmallInt&);
extern BigNum calc(const BigNum&);
Версия функции calc()
для языка С может быть вызвана как из программ на языке С, так и из программ на языке С++. Дополнительные функции с параметрами типа класса могут быть вызваны только из программ на языке С++, причем порядок объявления не имеет значения.
Упражнение 19.26. Объясните эти объявления и укажите, допустимы ли они:
extern "С" int compute(int *, int);
extern "С" double compute(double *, double);
Резюме
Язык С++ предоставляет несколько специализированных средств, предназначенных для решения ряда специфических проблем.
Некоторым приложениям требуется взять под свой контроль распределение памяти. Это можно сделать, определив собственные версии (в классе или глобально) библиотечных функций operator new()
и operator delete()
. Если приложение определяет собственные версии этих функций, выражения new
и delete
будут использовать соответствующую версию, определенную приложением.