在如下图所示的文件中展现的调用关系,在一个.cc(main.cc)文件中调用另一个.cc(test.cc)文件中的模板函数,编译过程出错。
// test.cc template<typename T> void function(T a) { ... } //test.h template<typename T> void function(T a); //main.cc int main() { int a=0; function(a); }c++从代码到可执行文件,经历了编译和连接两大步骤。在第一个步骤中,编译是指将一个个cpp文件及其include的.h头文件编译成一个个***文件,一个cpp及其include的头文件表示一个编译单元。当编译器将一个工程中的所有的cpp文件以分离的方式编译完毕后,再由连接器进行连接构成一个可执行文件。 按照上面的描述,上述出错的原因就很明显了,首先main.cc和test,h是一个编译单元,在这个编译单元中是没有模版函数的具体实现的,只有一个声明,因此编译器将这个调用模版函数的地方跳转到一个空的地址,希望连接器能在其他编译单元在找到这个函数的具体实现。在另一个编译单元中(print_num.cc)中由于没有函数调用模板函数,导致模板函数没有进行二次编译。因此连接器想给第一个编译单元找一个模板函数的实现的愿望显然是落空了。
方案1: 将模板函数的定义放在.h文件中。这样模板函数就可以和调用它的函数在同一个编译单元了,这样就不会出错了。
*方案2: 显式在模板函数所在的.cpp文件声明具体支持的数据类型。 如上案例:
// 模板函数的定义 ... // 添加实例化声明 template void function_name<int>(); template void function_name<float>();