头文件如何连接到相应的.cpp文件?

How is the header file connected to the corresponding .cpp file?

本文关键字:文件 cpp 连接 何连接      更新时间:2023-10-16

根据我所阅读和理解的内容,源文件中的#include指令,例如:main.cpp,只是将包含文件的内容复制到.cpp。因此,当我包含一个头文件时,例如:yum.hyum.h中的所有语句都复制到main.cpp中。

头文件将只有声明,实际定义将在相应的.cpp文件中,如yum.cpp

那么,在编译main.cpp时,编译器如何知道在yum.cpp中查找yum.h中提到的任何函数的定义?编译器如何知道也遵守yum.cpp文件,因为main.cpp文件或yum.h中都没有引用它。

另外,为什么yum.h应该包含在yum.cpp中?

这听起来像是一个愚蠢的问题。我是 OOP 和 C++ 的初学者,只是想了解正在发生的事情。

简短的回答:标头与其实现之间没有关系。一个可以存在而没有另一个,或者可以将两个放在名称不相关的文件中。

在编译main.cpp编译器如何知道查找yum.cppyum.h中提到的任何函数的定义?

编译器不知道。每次它看到对在yum.h或任何其他头文件中声明的内容的引用时,它都会留意相应的定义。

如果在编译器到达翻译单元末尾时定义不存在,它将不满意的引用写入其main.o输出,并注意它们的来源。这称为符号表

然后编译器编译yum.cpp,从其中的yum.h中找到定义,并将它们的位置写入yum.o的符号表中。

处理完所有cpp文件后,链接器将获取所有.o文件,并从中生成组合符号表。如果保留未满足的引用,则会发出错误。否则,它将main.o中的引用与yum.o中的相应符号链接,完成该过程。

考虑一个例子:假设yum.h声明了一个全局变量int yum = 0yum.cpp中定义的,main.cpp打印该变量。编译器生成main.o符号表,上面写着"我需要int yum在地址 1234 的定义",yum.o文件的符号表说"我在地址 9876 处有int yum"。链接器通过将 9876 放在地址 1234 中来匹配"我需要"和"我有"。

编译器不需要在其他代码文件中查找任何内容。
编译的结果是一个对象文件,该文件包含其他代码文件中定义的任何内容的占位符。为了制作这些占位符,编译器只需要合适的标头(声明、原型等)提供的信息。
填写占位符的步骤是链接器的工作,链接器在理论上是独立于编译器的工具。("理论上"如"可以是单个工具,表现得像两个单独的工具。

将带有声明的标头包含在执行实现(全部或部分声明的内容)的代码文件中的原因是一种广泛传播的最佳实践,因为它允许编译器在实现和声明不匹配时进行投诉。

那么在编译main时.cpp编译器如何知道在yum.cpp中查找yum.h中提到的任何函数的定义?

编译器没有。当它生成目标文件(这是编译的结果)时,它会在那里说 - 调用某某函数。然后是链接过程,其中所有对象文件和库链接在一起以生成可执行文件。当链接器看到所有对象文件并库时,它知道在哪里可以找到该函数(如果找不到它,则产生错误)。

即编译器如何知道也遵守 yum.cpp 文件,因为在 main.cpp 文件或 yum.h 文件中都没有引用它。

编译器也不知道这一点。程序员的工作是告诉编译器将所有必要的源文件编译为对象文件,并将它们全部传递给链接器。它可以在IDE中完成,可以对您隐藏,或者您可能必须使用实用程序make手动执行此操作。

还有为什么 yum.h 应该包含在 yum 中.cpp

当你编译C++程序时,你通常有类和它们的方法。为了能够在其他源文件中使用类,它的定义必须在那里可见,所以它转到一个标题。方法在文件中实现时也必须首先在类.cpp声明,以便.cpp必须包含它的标头。即使对于独立函数,让编译器将标头中的签名与实现中的签名匹配也更干净。