为什么要使用 'extern "C++"' ?

85
在这篇文章中,关键字extern可以跟随"C"或"C++"。为什么要使用'extern "C++"'?它是否实用?

6
好问题,欢迎来到 Stack Overflow :) - Paul Dixon
该文章现已移至https://learn.microsoft.com/en-us/cpp/cpp/extern-cpp?view=vs-2019。 - MathuSum Mut
11个回答

124

这种语言允许:

extern "C" {
  #include "foo.h"
}

如果foo.h包含一些需要C++链接的内容,会怎样?

    void f_plain(const char *);
    extern "C++" void f_fancy(const std::string &);

这就是保持链接器高兴的方法。


4
我不理解为什么会有负评。这是一个需要使用 extern C++ 的情况,而且它是合法的。 - Thomas L Holaday
1
我也不理解。这是使用 extern "C++" 的有效方法。 - Johannes Schaub - litb
3
它不仅是有效的,我还在实际应用中看到过它(这是我对它有所领悟的“噢哈”时刻)。请查看winnt.h文件。 - Michael Burr
不用担心,我给它投了赞成票是因为它被踩了,否则我本来不会这么做。并不是因为它不值得被赞成,而只是因为我没有想到。 - flarn2006

38

使用 extern "C++" 没有实际的理由。它仅仅显式地表明了隐含默认的连接性。如果你有一个类,其中一些成员具有 extern "C" 的连接性,你可能希望明确指出其他成员是 extern "C++"

请注意,C++ 标准定义了语法上的 extern "anystring"。它只为 extern "C"extern "C++" 给出正式的含义。如果编译器供应商喜欢,他们可以自由定义 extern "Pascal" 或甚至 extern "COM+"


这真的是对问题的完美答案。如果可以的话,我会给更多的投票。 - Randolpho
4
当你需要覆盖周围范围内的其他连接规范时,你可以使用它。 - Thomas L Holaday
8
我希望编译器支持 extern "Haskell" - user142019

25

我不确定你为什么需要这样做,但根据Sun的这篇文章,你可以在extern "C"块内使用extern "C++"来指定一组"C"函数中的某些函数具有本地C++链接。

extern "C" {
    void f();             // C linkage
    extern "C++" {
        void g();         // C++ linkage
        extern "C" void h(); // C linkage
        void g2();        // C++ linkage
    }
    extern "C++" void k();// C++ linkage
    void m();             // C linkage
}

这可能是为了处理在其中一个extern部分中包含头文件的情况。 - ThomasW

6

两种可能:

  • 如果您在extern "C"块中,可以通过指定嵌套的extern "C++"来再次获得C++语言链接。
  • 它保留了C++链接,因为它是定义C++的文档。谁比它本身更适合定义C++语言链接呢?它还提供了完整性。与signed/unsigned一样。

阅读这个答案也解释了extern "LanguageName"(即GCC有extern "Java")。


4

许多人都解释了 extern "C"。在C函数中调用C++库函数时,使用 extern "C++"。相关的子用例是在将C++库与带有主函数的C源代码链接时。请参阅维基页面获取更多详细信息:


3

C和C++使用不同的名称修饰规则。基本上,extern "C"告诉C++编译器将函数命名为C语言方式。


3
实际上,名称修饰仅是一种实现细节。这些语言本身根本没有任何修饰“规则”。各种编译器有不同的处理函数重载的方式。名称修饰只是一种流行的方法之一。 - James Curran

1

这个指定使用哪种链接约定。大多数语言都知道如何使用“C”风格函数进行链接。

您需要在以下两种情况下使用:

  • C或其他语言调用C++编写的函数
  • C++程序调用C编写的函数

示例:

// declared in function.h
void f1(void);

你的 C 代码 - 实际上其他编程语言也能链接到 C 函数 - 将无法链接到它,因为目标表中的名称将使用 C++ 命名规则。

如果你写下:

extern "C" void f1(void);

现在链接起来是因为它使用了C约定。


1

我使用extern "C"的主要原因是为了避免C++的名称修饰规则。如果你在一个.Net语言中工作,并想要PInvoke到特定的本地函数,这非常重要。唯一的方法是禁用名称修饰。


0

回答第二个问题,“它是否实用?”:

在标准头文件中,如<cmath>,它是实用的,也是几乎不可避免的。

想象一个仅包含头文件的库X.h,用一种C++和C的常见子集编写,并旨在从两种语言中使用。为了使C++用户受益,X.h包括<cmath>而不是<math.h>。但这对于C用户来说是行不通的,如果<cmath>的作者没有把所有内容夹在extern "C++" { ... }中。


-1
短暂而简单的回答是,您可以使用extern C来告诉编译器不要使用名称重整。这意味着您可以在同一项目中链接C和C ++代码的部分。

但是,问题正文也问了詹姆斯回答的问题。 - Dominic Rodger
1
extern "c" 很容易在谷歌上搜索到,但 extern "c++" 是一个有趣的问题,如果我错了,我会收回这个说法! - Paul Dixon
对我来说,这似乎是一个关于为什么要使用其中任何一种的问题。现在有更好的答案,所以这并不重要。 - James Brooks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接