extern "C" 声明某些东西具有C 语言链接。这不同于外部链接和内部链接。默认情况下,C++ 程序中的所有内容都具有 C++ 语言链接,但您可以通过指定 extern "C++" 来重申这一点。
外部链接意味着该名称对单独编译的其他源文件可见,假设您包含正确的标题或提供正确的声明。这就是允许您在a.cpp 中定义函数foo 并从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) 和 @987654343 @等等。在 C++ 中,标记为 extern "C" 的单个重载会根据给定平台的 C 方案进行重载,而其他重载则保留其正常的重载名称。
声明模板extern "C" 将要求所有实例化为extern "C",因此与“只有一个给定名称的函数可以是extern "C"”规则相矛盾。
虽然 C 没有 structs 的名称修改,但只能有一个 struct 具有给定名称。因此,禁止 extern "C" 用于类模板也很有意义 --- 模板定义了一系列具有相同名称的类,那么哪个对应于 C struct?