【问题标题】:Is extern keyword required here, const in cpp file这里是否需要 extern 关键字,cpp 文件中的 const
【发布时间】:2014-07-11 13:07:07
【问题描述】:

如果我有头文件

namespace Bob
{
    extern const T x;
};

在源文件中

extern const T Bob::x = 123;

源文件中的第二个extern 是必需的还是可选的?

我已搜索并发现相互矛盾的信息。

从此网页: http://msdn.microsoft.com/en-us/library/357syhfh.aspx

但是要在 C++ 中获得相同的行为,您必须将 const 变量 [在源文件中] 声明为:

extern const int i = 2;

【问题讨论】:

  • @LightnessRacesinOrbit 你怎么能写出这么小的cmets?
  • @NeilKirk 他是个很酷的人,我们不是 :)
  • 老实说,在得到答案和cmets之后,我对这件事没有更多的启发。

标签: c++


【解决方案1】:

通常,extern 关键字告诉编译器不要定义符号,因为它将在其他地方定义。所以写例如

namespace Bob {
    extern T x;
}

没有定义变量x,而是声明它。您可以拥有任意数量的extern 声明。但是,如果您不提供定义,则链接将失败。所以你必须定义

T Bob::x;

在代码中的某个地方提供定义。

const 关键字在这里有点特别,因为它暗示了内部链接。这意味着,x 的定义在定义它的特定编译单元之外将不可见。要改变这种行为,你需要写

    extern const T Bob::x = 123;

如果您希望 x 成为 const 并从其他编译单元中引用它。

----又一次修改----
只是要绝对清楚: 如果应该在其编译单元之外引用 const 变量,那么您必须显式声明它 extern

但是,如果声明与定义分开给出,那么定义不一定需要再次指定关键字extern。另一个演示示例:

myheader.h

extern const int i;

这声明了i 一个带有外部链接的const 整数,但没有定义它。

ma​​in.cpp,版本 1

#include "myheader.h" //Through the include, the above declaration of `i` comes before its definition.

const int i=123; // Although the `extern` modifier is omitted here,
                 // it's still in effect because we already declared `i` as `extern`
                 // Therefore it makes no difference here, whether or not you specify `extern` again.
                 // The compiler knows this is a definition either way, because of the initialization.

ma​​in.cpp,第 2 版

//#include "myheader.h"

extern const int i=123; // this line is declaration and definition in one, because we did not include
                        // the declaration from myheader.h. Thus, to tell the compiler that you want
                        // `i` with external linkage, you MUST specify `extern`. Otherwise you'll get
                        // internal linkage.

我希望现在这一切对你有意义。

【讨论】:

  • “既非必需也非可选”是否意味着“不允许”?
  • 不可以,但要改变意思。如果存在 extern,您可以使用该变量但不能定义它。
  • 你不需要定义中的extern,只要你在#include的头文件中声明它为extern即可。这样也更安全。
  • @SanderDeDycker:我同意,如果我们在定义之前包含 extern 声明就不需要了,但为什么它会更安全?
  • @AlexanderTobiasHeinrich :包含标题将保护您免受声明和定义之间的意外差异。此外,在定义中不添加extern意味着它只会在需要时才具有外部链接(当从头文件中删除声明时,它会自动恢复为内部链接)
【解决方案2】:

您可以使用staticextern 关键字控制符号的链接。对于非常量符号,默认链接是 extern,对于命名空间范围内的 const 符号,默认链接是 static(即内部)。这对 C++ 有效,但对 C 无效(您必须将其声明为 static 以使其具有内部链接)。

如果你有

const int i = 2;

到 .c 文件中,然后通过声明将其用于另一个单元

extern const int i;

这在 C 中很好,因为该变量默认具有外部链接(并且使用 extern 关键字指示编译器将其查找到另一个单元中),但在 C++ 中相同

const int i = 2;

到一个 .cpp 文件(我写的东西是固定的)有内部链接,它必须用

定义
extern const int i = 2;

明确地具有外部链接,并能够与另一个单元一起使用

extern const int i;

最后,当你初始化一个全局变量时,你总是在你正在做它的模块中定义它,这意味着以下是完全有效的:

#include <iostream>
using namespace std;

#define T int

extern const T x; // This is a declaration
extern const T x = 123; // This is a definition

int main() {

  std::cout << x; // 123

  return 0;
}

这意味着第二个'extern'关键字也是不必要的。

【讨论】:

  • 所以您的回答是否定的,这不是必需的吗?这与其他答案不同。
  • 那很糟糕。我之前在两个不同的编译器上以不同的方式处理 const 上缺少的 extern 时被这个烧毁了。我不能简单地试验一个编译器。另外,我的问题是关于不同的文件。
  • @NeilKirk 编译器只要符合标准就应该做同样的事情。确保您没有将部分代码编译为 C 和其他一些东西作为 C++。还要确保您在声明中使用了正确的 extern 关键字。
  • 他们应该,但他们没有。当缺少必需的 extern 关键字时,VS 和 gcc 的行为有所不同。这是一个很难简化的庞大项目。
  • @NeilKirk 这可能是一个错误或类似的东西(也许在 MSVC 中),但这应该是他们应该遵守的行为。抱歉,我无法帮助您完成之前的项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2020-05-20
  • 2011-01-20
  • 2011-05-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
相关资源
最近更新 更多