头文件和源文件分类原因
分离不是为了好看,而是由C++的分离式编译 (Separate Compilation) 模型决定的
- 编译 (Compilation)
- 编译器一次只处理一个
.cpp文件。当编译器处理main.cpp时,如果其中包含了#include "my_math.h",预处理器会把my_math.h的内容原封不动地“粘贴”到main.cpp的开头 - 这样,编译器就知道
add函数的存在和正确用法,即使它的具体代码在my_math.cpp里。编译成功后,每个.cpp文件都会生成一个对应的目标文件(.o或.obj)
- 编译器一次只处理一个
- 链接 (Linking)
- 链接器将所有生成的目标文件(如
main.o,my_math.o)以及所需的库文件“链接”在一起,最终生成一个可执行文件。 - 这一步,链接器会去寻找
main.o中对add函数的调用所对应的具体实现,它会在my_math.o中找到这个实现,并将它们关联起来
- 链接器将所有生成的目标文件(如
分离带来的好处:
- 模块化与封装:头文件定义了模块的公共接口(API),而实现细节则被隐藏在
.cpp文件中 - 避免重复定义:C++有“单一定义规则 (One Definition Rule, ODR)”,即一个非内联的函数或变量在整个程序中只能被定义一次。如果将函数定义放在头文件中,那么每个包含该头文件的
.cpp文件都会有一个该函数的定义,链接时就会因“重复定义”而报错 - 提高编译效率:在一个大型项目中,如果只修改了一个
.cpp文件,只需重新编译这一个文件,然后将所有目标文件重新链接即可,无需重新编译整个项目,大大节省了时间