编译+链接:
分离编译: 我们将fun()函数的定义放在MoBan.cpp中,将fun()函数的声明放在MoBan.h中进行编译,结果如下:
分析: 编译器在“预编译阶段”会将#include包含的文件拷贝进当前Test.cpp文件中,那么经过预编译阶段后Test文件中便会包含模板的声明,在“编译阶段”Test文件中的Test<int> t相当于告诉编译器要将模板类实例化为Test<int>类型,但是当模板分离编译时,此时Test文件中只会实例化出fun()函数的声明,而MoBan.cpp中fun()函数的定义并不会实例化,所以当在“链接阶段”符号表的重定位时并不会找到fun()函数的地址。所以出现无法解析外部符号的错误。如下图:
声明/定义放在一块编译: 我们将fun()函数的声明与定义均放在MoBan.hpp中进行编译,结果如下:
分析: 当我们将模板的声明与定义放在同一个MoBan.hpp文件中时,在“预编译阶段”便会将模板的定义也包含进Test文件中,于是乎在“编译阶段”Test文件便会实例化出函数的定义,进而在“链接阶段”便会找到函数的地址。
其实,还有一种可以解决模板分离编译的方法,那就是在模板声明的MoBan.h中进行显式实例化,通过定义template class Test<int>达到对模板显式实例化的作用。但我们不推荐使用此种方式:1、实例化依赖于调用者。2、旧的编译器可能不支持。