多次#included 保护头文件如何位于不同的翻译单元内?

Phy*_*ian 0 c++ include-guards include visual-studio translation-unit

我知道 #inclusion 通常被描述为文本复制粘贴预处理器指令。现在,如果标头受到 #include 保护或 #pragma 一次,那么我们如何描述第一个翻译单元之后实际发生的情况到 #include 所述标头?

Bri*_*ian 6

不存在“第一”翻译单元。所有翻译单元在概念上都是并行翻译的(当然,实际上您可能最终一次编译一个单元,但这并不重要)。

每个翻译单元都从一张白纸开始。从技术上讲,这并不完全正确,因为您可以#define在命令行添加 s,并且还有一些预定义的宏,但无论如何,没有翻译单元具有#define在任何其他翻译单元中执行的 s 的“记忆”。因此,尽管有防护措施,标头仍可能被#include多次删除。只是它不会被#include多次分解到一个翻译单元中

这意味着您仍然必须注意避免多个定义:例如,如果您的标头包含全局变量,那么您必须确保它是const(因此它将具有内部链接)或显式声明它inline(将所有定义折叠为一个)或extern(抑制标头中的定义,以便您可以将定义放入单个翻译单元中)。

尽管包含防护并不能阻止跨多个翻译单元的多个定义,但它们确实阻止单个翻译单元内的多个定义,这很重要,因为即使某些实体可能在程序中定义多次,但仍然不允许多个定义出现在同一翻译单元中。例如,如果inline标头中有一个全局变量,则多个翻译单元可以包含该标头,并且定义将在链接时全部折叠为单个定义,但如果任何一个翻译单元定义了该标头,您将收到编译错误多次可变。因此,这样的标头必须具有包含保护。