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

C++ 为什么我可以在包含const int的多个cpp文件中包含一个头文件,并且没有编译器错误?,c++,compilation,header,include,C++,Compilation,Header,Include,假设我有文件a.cpp b.cpp和文件c.h。这两个cpp文件都包括c.h文件。头文件包含一组const int定义,当我编译它们时,我没有得到任何错误,但是我可以像访问全局变量一样访问这些const。所以问题是,如果我有多个const定义,并且这些const int具有类似全局的作用域,为什么我没有得到任何编译错误呢?这样做时,您可以在每个对象文件中为头中的每个常量创建一个单独的const变量。这不是问题,因为它们是const这是因为命名空间范围中的const声明意味着内部链接。具有内部链接

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

这样做时,您可以在每个对象文件中为头中的每个常量创建一个单独的
const
变量。这不是问题,因为它们是
const

这是因为命名空间范围中的
const
声明意味着内部链接。具有内部链接的对象仅在定义该对象的转换单元中可用。因此在某种意义上,你在
c.h
中的
const
对象实际上是两个不同的对象,一个是
a.cpp
的内部对象,另一个是
b.cpp
的内部对象

换句话说,

const int x = ...;
相当于

static const int x = ...;

类似于

extern int x;
因为命名空间范围中的非
const
声明意味着外部链接。(在最后一种情况下,它们实际上并不等价。
extern
,以及显式指定外部链接,生成对象的声明,而不是定义。)

<>请注意,这是C++特有的。在C中,
const
不会更改隐含的链接。原因是C++委员会希望你能够写< /P>
const int x = 5;

在标题中。在C中,包含多个文件的报头将导致链接错误,因为您将多次定义同一个对象。

< P>从当前C++标准…

7.1.1存储类别说明符 7) 在没有存储类说明符的命名空间作用域中声明的名称具有外部链接,除非由于以前的声明而具有内部链接,并且如果该名称未声明为常量声明为常量而未显式声明为extern的对象具有内部链接。

3.5程序和链接 2) 当名称具有内部链接时,它所表示的实体可以通过同一翻译单元中其他作用域的名称来引用


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

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


#define的某些用法可以替换为内联函数。有些-使用
const
变量声明。由于#define往往位于头文件中,因此用
const
s替换这些头文件可以更好地工作。因此,“常量默认为静态”规则。

每个对象文件都有自己的“定义”吗
const int x = 5;