为什么我可以在包含const int且没有编译器错误的多个cpp文件中包含头文件?

时间:2012-04-01 23:09:57

标签: c++ compilation header include

我们假设我有文件a.cpp b.cpp和文件c.h.两个cpp文件都包含c.h文件。头文件包含一堆const int定义,当我编译它们时,我没有错误,但我可以访问这些const,就像它们是全局变量一样。所以问题是,如果我有多个const定义以及这些const int具有类似全局的范围,为什么不能得到任何编译错误?

4 个答案:

答案 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默认是静态的”规则。