Ответ 1
Это особенно запутанная тема. Пусть атака §7.5 "Спецификации привязки" [dcl.link].
1) Все типы функций, имена функций с внешней связью и имена переменных с внешней связью имеют языковые связи.
Обратите внимание, что свойство языковой привязки применяется к двум совершенно различным типам сущностей: типам и именам.
Функция имеет в общем виде невидимый бит информации, который идентифицирует, какой ABI он соответствует: соглашениям о вызовах C, Pascal, Fortran, все могут быть указаны для использования стека по-разному, поэтому вызов их через указатель требует знания невидимого языкового тега.
Имя переменной или функции с другого языка можно получить синтаксически через С++ или с другого языка, ссылающегося на объявление С++. Но не каждый язык может соответствовать схеме именования С++ и модели OO. Таким образом, интерфейсы в этой схеме не включают классы.
Поскольку эти вещи управляются отдельно, возможно иметь что-то с другой связью в своем типе (вызывающие соглашения) и его имя (символ линкера).
4) Спецификация спецификации привязки. Когда гнездо спецификации привязки, самый внутренний определяет язык связь. Спецификация связи не устанавливает область действия. Спецификация привязки должна выполняться только в области пространства имен (3.3). В спецификации привязки указанная языковая связь применяется к типам функций всех деклараторов функций, имен функций с внешней привязкой и именам переменных с внешней связью, объявленной в спецификации привязки. Связи языка C игнорируются при определении языковой привязки имен членов класса и типа функции функций-членов класса.
extern "C" {}
влияет на все объявления функций, включая указатели и ссылки, кроме функций-членов. Поскольку функция может быть определена только в пространстве имен или как член, функции C могут быть определены только в области пространства имен.
В стандарте приведен пример:
extern "C" typedef void FUNC_c();
class C {
// the name of the function mf1 and the member
// function’s type have C++ language linkage; the
// parameter has type pointer to C function
void mf1(FUNC_c*);
// the name of the function mf2 and the member
// function’s type have C++ language linkage
FUNC_c mf2;
// the name of the data member q has C++ language
// linkage and the data member’s type is pointer to
// C function
static FUNC_c* q;
};
Вы можете эмулировать поведение, которое хотите, используя typedef
. Из другого примера в § 7.5/4,
extern "C" typedef void FUNC();
// the name f2 has C++ language linkage and the
// function’s type has C language linkage
FUNC f2;
Объединяя эти примеры с вашими, вы можете иметь
extern "C" typedef void callback_t();
callback_t A_callback; // declare function with C++ name and C type
struct A
{
static callback_t &callback; // not a member function
};
// in source file:
// definition matches semantics of declaration, although not syntax
void A_callback() { ... }
// define static member reference
callback_t &A::callback = A_callback;
g(A::callback); // call syntax is emulated
На практике это редко имеет значение. C и С++ используют совместимые соглашения о вызовах на большинстве платформ (см. Комментарии Джонатана Вакели на этой странице для исключений), если вы не пытаетесь передать или вернуть тип класса, отличного от POD С++. Это менее реализованная функция С++ из-за запутанной перегрузки терминов и концептуальных различий, от тонкой до академической.