extern "C"
заявляет, что есть C языковая связь. Это отличается от внешняя связь и внутренняя связь. По умолчанию все в программе на C++ имеет связь на языке C++, хотя вы можете повторить это, указав extern "C++"
.
внешняя связь означает, что это имя видно другим исходным файлам, скомпилированным отдельно, при условии, что вы включаете правильные заголовки или указываете правильные объявления. Это то, что позволяет определить функцию foo
в a.cpp
и называть ее от b.cpp
. Большинство имен в области пространства имен в программе на C++ имеют внешнюю связь. Исключением являются те, которые имеют внутренняя связь, а те, которые имеют , не связаны. Вы можете явно отметить что-то как внешнее соединение, указав extern
. Это отличается от extern "C"
.
внутренняя связь означает, что имя уникально для текущего блока компиляции, и вы не можете получить доступ к переменной или функции из другого исходного файла. Переменные и функции области видимости файла static
имеют внутреннюю связь. Кроме того, const
целые переменные в области пространства имен, которые инициализируются константным выражением, по умолчанию имеют внутреннюю привязку, хотя вы можете переопределить ее с явным extern
.
И, наконец, локальные переменные и классы имеют нет связи. Имена локальны для функции, в которой они объявлены, и к ней нельзя получить доступ извне этой функции. Вы можете использовать extern
, чтобы указать, что вы действительно хотите получить доступ к переменной в области пространства имен.
Шаблоны не могут быть определены в локальном масштабе, но могут иметь внутреннюю или внешнюю связь.
int i; // namespace scope variable has external linkage
extern int j; // explicitly mark j with external linkage
static int k; // k has internal linkage
int const n=42; // internal linkage
extern int const m=99; // external linkage
void foo(); // foo has external linkage; it may be defined in this source file or another
extern void foo(); // explicitly mark foo with external linkage
static void bar(); // bar has internal linkage, and must be defined in this source file
void foo(){} // definition of foo, visible from other source files
void bar(){} // definition of bar, not visible from other source files (internal linkage)
static void baz(){} // declare and define baz with internal linkage
template<typename T> void foobar(){} // foobar has external linkage
template<typename T>
static void foobaz(){} // foobaz has internal linkage
void wibble()
{
int i; // local, no linkage
extern int i; // references i, declared above with external linkage
}
extern "C"
{
int i2; // namespace scope variable has external linkage, and "C" linkage
extern int j2; // explicitly mark j2 with external linkage and "C" linkage
static int k2; // k2 has internal linkage and "C" linkage
int const n2=42; // internal linkage and "C" linkage
extern int const m2=99; // external linkage and "C" linkage
void foo2(); // foo2 has external linkage and "C" linkage
static void bar2(); // bar2 has internal linkage and "C" linkage
void foo2(){} // definition of foo2, still with external linkage and "C" linkage
void bar2(){} // definition of bar2, still with internal linkage and "C" linkage
static void baz(){} // declare and define baz with internal linkage
}
Сообщение об ошибке правильно --- шаблоны не могут иметь extern "C"
связи.
На базовом уровне шаблоны не могут иметь связи extern "C"
, потому что они несовместимы с C. В частности, шаблон не просто определяет один класс или функцию, а семейство классов или функций, которые имеют одно и то же имя , но отличаются их параметрами шаблона.
Только одна функция с заданным именем может быть объявлена extern "C"
. Это имеет смысл, если вы думаете об изменении имени --- в C, функция foo
обычно называется либо foo
, либо _foo
в таблице символов.В C++ может быть много перегрузок foo
, поэтому подпись включена в «искаженное» имя в таблице символов, и вы можете получить $3fooV
или foo$void
или что-то еще, чтобы отличить foo(void)
от foo(int)
и так далее. В C++ единственная перегрузка, которая отмечена extern "C"
, получает искалечен согласно схеме C для данной платформы, тогда как другие перегрузки сохраняют свое обычное искаженное имя.
Объявление шаблона extern "C"
требует всей инстанциации быть extern "C"
, что, таким образом, противоречит «только одна функции с заданным именем может быть extern "C"
» правилом.
Хотя C не имеет названия для struct
s, может быть только один struct
с заданным именем. Таким образом, запрет на extern "C"
для шаблонов классов имеет смысл --- шаблон определяет семейство классов с тем же именем, что соответствует C struct
?
Я только что заметил, что вы добавили щедрость за вопрос. Кажется странным, поскольку я считаю, что ответ, который я дал, был правильным и полным. Что вы еще не понимаете? - Я заметил, что вы также удалили начальную часть вопроса, сделав большую часть ответа бесполезным ... Вы должны рассмотреть возможность добавления комментариев или другого вопроса, если у вас все еще есть проблемы. Изменение вопроса не помогает никому - люди, которые уже ответили, не получают уведомления, люди, просматривающие q и a, будут сбиты с толку ответами, которые не освобождены ... –
Вернулся к версии перед удалением, так что это имеет смысл , – Suma
@David: Похоже, что BE Student заинтересован в выдаче очков специально для USER. –