为什么在 C++ 中允许对 const 全局变量进行多重定义,而在 C 中却不允许?

2022-01-23 00:00:00 c constants c++ one-definition-rule

由于单一定义规则,在 C 或 C++ 中不允许对全局变量进行多重定义.但是,在 C++ 中,一个 const 全局变量可以在多个编译单元中定义而不会出错.这与 C 中的不同.

Multiple definition of a global variable is not allowed in C or C++ due to the One Definition Rule. However, in C++ a const global variable can be defined in multiple compilation units with no error. This is not the same as in C.

为什么 C++ 允许,而 C 不允许?与 C 相比,为什么 C++ 中 const 全局变量的用法和行为与非 const 全局变量有这种不同?C++ 和 C 在 const 方面发生了什么?

Why does C++ allow this while C does not? Why does the usage and behaviour of a const global differ from a non-const global in this way in C++ compared to C? What is happening under the covers with C++ and C with respect to const?

例如,这在 C++ 中是允许的,但在 C 中是错误的:

For example this is allowed in C++, but wrong in C:

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;
int main()
{
    cout << Foo << endl;
    return 0;
}

这对 C 来说很好,但对 C++ 来说是错误的:

And this is fine with C, but wrong with C++:

// Foo.cpp
const int Foo = 99;

// Main.cpp
extern const int Foo;
int main()
{
    cout << Foo << endl;
    return 0;
}

推荐答案

// Foo.cpp
const int Foo = 99;

// Main.cpp
const int Foo = 99;

命名空间范围内的

const 变量具有 internal 链接.所以它们基本上是两个不同的变量.没有重新定义.

const variable at namespace scope has internal linkage. So they're basically two different variables. There is no redefinition.

来自@David 的评论,3.5/3 [basic.link]:

From @David's comment, 3.5/3 [basic.link]:

具有命名空间范围的名称 (3.3.5)如果是名称,则具有内部链接的
― 对象、引用、函数或显式的函数模板声明为静态或,
― 一个物体或明确声明的引用const 且均未明确声明extern 之前也没有声明过外部链接;或
― 数据成员一个匿名工会的成员.

A name having namespace scope (3.3.5) has internal linkage if it is the name of
― an object, reference, function or function template that is explicitly declared static or,
― an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage; or
― a data member of an anonymous union.

<小时>

在第二种情况下,你应该这样做(正确的方法):


In the second case, you should be doing this (correct way):

//Foo.h
extern const int Foo; //use extern here to make it have external linkage!

// Foo.cpp
#include "Foo.h"
const int Foo = 99; //actual definition goes here

// Main.cpp
#include "Foo.h"
int main()
{
   cout << Foo << endl;
}

相关文章