【问题标题】:Why is it that I can include a header file in multiple cpp files that contains const int and not have a compiler error?为什么我可以在多个包含 const int 且没有编译器错误的 cpp 文件中包含一个头文件?
【发布时间】:2012-04-15 16:25:03
【问题描述】:
假设我有文件 a.cpp b.cpp 和文件 c.h。两个 cpp 文件都包含 c.h 文件。头文件包含一堆 const int 定义,当我编译它们时,我没有收到任何错误,但我可以访问这些 const ,就好像它们是全局变量一样。那么问题来了,如果我有多个 const 定义并且这些 const int 具有类似全局的作用域,为什么我不会收到任何编译错误?
【问题讨论】:
标签:
c++
compilation
header
include
【解决方案1】:
这是因为在命名空间范围内的 const 声明意味着内部链接。具有内部链接的对象仅在定义它的翻译单元中可用。所以从某种意义上说,你在c.h 中拥有的一个const 对象实际上是两个不同的对象,一个在a.cpp 内部,一个在b.cpp 内部。
换句话说,
const int x = ...;
等价于
static const int x = ...;
同时
int x;
类似于
extern int x;
因为命名空间范围内的非const 声明暗示了外部链接。 (在最后一种情况下,它们实际上并不等价。extern 以及显式指定外部链接会生成对象的声明,而不是定义 .)
请注意,这是特定于 C++ 的。在 C 中,const 不会更改隐含的链接。 原因是 C++ 委员会希望你能够编写
const int x = 5;
在标题中。在 C 中,包含在多个文件中的标头会导致链接器错误,因为您将多次定义同一个对象。
【解决方案2】:
从当前的 C++ 标准...
7.1.1 存储类说明符
7) 在没有存储类说明符的命名空间范围内声明的名称具有外部链接,除非它由于先前的声明而具有内部链接并且如果它没有声明为 const。 声明为 const 且未显式声明为 extern 的对象具有内部链接。
3.5 程序与联动
2) 当名称具有内部链接时,它所表示的实体可以由同一翻译单元中其他范围的名称引用。
预处理器使头文件中定义的内容包含在当前翻译单元中。
【解决方案3】:
这样做时,您会在每个目标文件中为标题中的每个常量创建一个单独的const 变量。这不是问题,因为他们是const。
【解决方案4】:
真正的原因:因为#define是邪恶的,需要死。
#define 的某些用法可以替换为内联函数。一些 - 带有const 变量声明。由于#define 往往在头文件中,用consts 替换那些更好的工作。因此,“consts 在默认情况下是静态的”规则。