为什么我可以在多个包含const int的cpp文件中包含一个头文件,而不会出现编译器错误

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      更新时间:2023-10-16

让我们假设我有文件a.cpp b.cpp和文件c.h。这两个cpp文件都包括c.h文件。头文件包含一堆const int定义,当我编译它们时,我没有得到任何错误,但我可以访问这些const,就好像它们是全局变量一样。那么问题来了,如果我有多个const定义,并且这些const int具有类似全局的作用域,为什么我不会得到任何编译错误呢?

这是因为命名空间范围内的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中,多个文件中包含的头会导致链接器错误,因为您将多次定义同一个对象。

从当前的C++标准。。。

7.1.1存储类别说明符

7) 在没有存储类说明符的命名空间作用域中声明的名称具有外部链接,除非它由于以前的声明而具有内部链接,并且前提是它没有声明为const声明为const和未显式声明为extern的对象具有内部链接

3.5程序和链接

2) 当一个名称具有内部链接时,它所表示的实体可以由同一翻译单元中其他作用域的名称引用。

预处理器使在标题中定义的内容包含在当前翻译单元中。

执行此操作时,将在每个对象文件中为标头中的每个常量创建一个单独的const变量。这不是问题,因为它们是const

真正的原因:因为#define是邪恶的,需要死亡。

#define的某些用法可以用内联函数代替。一些-带有const变量声明。由于#define往往在头文件中,因此用const替换这些头文件会更好。因此,"consts在默认情况下是静态的"规则。