一、模板不能分离编译
1、什么是分离编译
在使用分离编译时,程序或者库通常被分割成多个源文件(.cpp文件),每个源文件都包含程序的一部分功能或者库的一部分实现。每个源文件都被独立编译成目标文件(.o文件或者.obj文件),然后在链接阶段将这些目标文件链接在一起形成最终的可执行文件或者库文件,简单来说就是C++中将函数和类的定义放到.cpp中函数和类的声明放到.h中
2、简述编译过程
(1)预处理
在这个阶段,预处理器处理源文件,执行诸如宏展开、条件编译,去掉注释,
(2)编译
编译器接收预处理后的中间文件,将其转换成相应的汇编代码。在这个阶段,源代码被翻译成机器可以理解的汇编语言。
(3)汇编
将汇编代码转换为机器可以识别的二进制代码
(4)链接
链接阶段是将所有的目标文件(包括已编译的源文件、库文件等)连接在一起,形成最终的可执行文件或者库文件的过程。在链接阶段,编译器会将函数的声明和定义联系起来,以解决所有的函数引用。这包括将模板函数的实例化代码与相应的调用进行匹配。
3、模板函数在编译过程时的操作
-
预处理阶段:
模板函数:模板函数的声明和定义也通常位于头文件中。与普通函数不同的是,模板函数的定义也可能位于头文件中,但如果定义在.cpp文件中,那么在预处理阶段,编译器将无法展开模板函数的定义。 -
编译阶段:
模板函数:如果模板函数的定义位于头文件中,编译器可以在编译阶段将模板函数的代码实例化为特定类型的函数代码。但如果模板函数的定义位于.cpp文件中,则在编译阶段编译器将无法实例化模板函数的代码,因为模板的完整定义并不在当前的编译单元中。 -
汇编阶段:
模板函数:如果模板函数的定义位于头文件中并已经实例化,那么在汇编阶段编译器可以将模板函数的实例化代码转换成机器代码。但如果模板函数的定义位于.cpp文件中,则在汇编阶段编译器无法生成模板函数的实例化代码。 -
链接阶段:
模板函数:如果模板函数的实例化代码已经生成,那么在链接阶段链接器可以正确地将模板函数的实例化代码链接到最终的可执行文件或库文件中。但如果模板函数的定义位于.cpp文件中,链接器将无法解析对模板函数实例化的引用,因为目标文件中并没有相关的定义。因为不知道模板的类型,所以不知道具体应该调用哪个函数,模板的类型是在实例化之后才得到的,
4、如何解决
有模板的函数或者类不要使用分离编译,而是把定义和声明都放到.h头文件中,