我们假设我有文件a.cpp b.cpp和文件c.h.两个cpp文件都包含c.h文件。头文件包含一堆const int定义,当我编译它们时,我没有错误,但我可以访问这些const,就像它们是全局变量一样。所以问题是,如果我有多个const定义以及这些const int具有类似全局的范围,为什么不能得到任何编译错误?
答案 0 :(得分:5)
这是因为命名空间范围内的const
声明意味着内部链接。具有内部链接的对象仅在定义它的转换单元中可用。从某种意义上说,const
中的c.h
对象实际上是两个不同的对象,一个在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中,从多个文件中包含的头将导致链接器错误,因为您将多次定义同一个对象。
答案 1 :(得分:2)
从目前的C ++标准......
7.1.1存储类说明符
7)在没有存储类说明符的命名空间作用域中声明的名称具有外部链接,除非由于先前的声明而具有内部链接,并且未将其声明为const。 声明为const且未显式声明为extern的对象具有内部链接。
3.5程序和链接
2)当名称具有内部链接时,其表示的实体可以通过相同翻译单元中其他范围的名称来引用。
预处理器会导致标头中定义的内容包含在当前转换单元中。
答案 2 :(得分:0)
执行此操作时,您将在每个目标文件中为标题中的每个常量创建单独的const
变量。这不是问题,因为它们是const
。
答案 3 :(得分:0)
真正的原因:因为#define
是邪恶的,需要死亡。
#define的一些用法可以用内联函数替换。一些 - 使用const
变量声明。由于#define往往位于头文件中,因此用const
替换那些更好的工作。因此,“consts默认是静态的”规则。