预处理器定义对于当前编译单元是本地的。
当然有复杂的情况,但重点是:
尝试将 .cpp(源)文件视为不同的实体。如果你不做真正奇怪的事情,那么如果你删除所有 .cpp 文件,除了你打扰的那个,你仍然可以编译,因为在编译阶段不需要定义,你只关心事物的名称(声明)。
因此,一次编译 N 个源文件本质上是这样的:
[ *.H + SOURCE1.CPP ] --> SOURCE1.O
[ *.H + SOURCE2.CPP ] --> SOURCE2.O
...
[ *.H + SOURCEN.CPP ] --> SOURCEN.O
其中每一行都是一个不同的编译单元,它将 SourceX.CPP 和包含的头文件呈现到一个对象文件中。所以我们得到了 N 个单独的东西。
这样,如果您不更改公共头文件,那么您不必重新编译未修改的源文件。当然,如果你修改了一个源文件,你必须重新编译它。最后,如果你修改了一个公共头文件,那么你必须重新编译每个包含它的源文件。这里我不得不提一下,在编译阶段之前,所有
#inlude "filename.ext"
行(预处理器指令)都将替换为 filename.ext 文件的确切内容,无论它是什么。
然后链接是一个不同的问题,在那个阶段,目标是从 N 个目标文件创建一个文件。(我重复一遍,这是简单的情况)
这是链接:
[ SOURCE1.O + SOURCE2.O + ... + SOURCEN.O ] --> EXECUTABLE.FILE
将受影响的目标文件想象成一袋值和算法(函数定义)。例如,包中的某处必须恰好有一个
main
函数(定义),因此链接器在您执行程序时肯定会知道要做什么。
希望你明白了
猜猜会发生什么,如果将全局函数的定义写入头文件,然后将其包含在两个单独的编译单元中,然后尝试链接它们。
答案:链接器错误 - 多个定义,因为您可以单独编译它们。