存在问题的代码:
test.h:
#include <iostream>using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2);
test.cpp:
#include "test.h"using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2){ cout<<t1<<t2<<endl;}
main.cpp:
#include "test.h"int main(){ string str("ljt"); int i=5; func(str,5);}
编译后果:
[root@localhost cpptest]# g++ test.cpp test.h main.cpp -o test/tmp/ccp1HXnh.o:在函数‘main’中:main.cpp:(.text+0x5d):对‘void func<std::string, int>(std::string, int)’未定义的援用collect2: 谬误:ld 返回 1
阐明了在main.cpp中没有找到函数func的定义。
查看起因:
对test.cpp只进行编译不进行链接:
[root@localhost cpptest]# g++ -c test.cpp [root@localhost cpptest]# nm -C -n test.o U __cxa_atexit U __dso_handle U std::ios_base::Init::Init() U std::ios_base::Init::~Init()0000000000000000 t __static_initialization_and_destruction_0(int, int)0000000000000000 b std::__ioinit000000000000003d t _GLOBAL__sub_I_test.cpp
会发现符号表中不存在func函数,也就是编译出的二进制文件没有为func分配内存空间。
起因是:模板只有在应用的时候才进行实例化。
改过后代码:
test.cpp:
#include "test.h"using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2){ cout<<t1<<t2<<endl;}void func1(string str,int num){ func(str,num); //实例化,调配空间}
编译后:
[root@localhost cpptest]# g++ -c test.cpp //-c:只编译不链接
[root@localhost cpptest]# nm -C -n test.o U __cxa_atexit U __dso_handle U __gxx_personality_v0 w __pthread_key_create U _Unwind_Resume U std::ostream::operator<<(int) U std::ostream::operator<<(std::ostream& (*)(std::ostream&)) U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() U std::ios_base::Init::Init() U std::ios_base::Init::~Init() U std::cout U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)0000000000000000 W void func<std::string, int>(std::string, int)0000000000000000 T func1(std::string, int)0000000000000000 b std::__ioinit0000000000000000 r __gthread_active_p()::__gthread_active_ptr0000000000000063 t __static_initialization_and_destruction_0(int, int)00000000000000a0 t _GLOBAL__sub_I__Z5func1Ssi
能够看到函数符号func1(std::string, int)、void func<std::string, int>(std::string, int)。
[root@localhost cpptest]# g++ test.cpp test.h main.cpp -o test[root@localhost cpptest]# ls -rtl总用量 32-rw-r--r-- 1 root root 92 12月 21 10:41 test.h-rw-r--r-- 1 root root 172 12月 21 13:00 test.cpp-rw-r--r-- 1 root root 86 12月 21 13:00 main.cpp-rw-r--r-- 1 root root 3912 12月 21 13:01 test.o-rwxr-xr-x 1 root root 13952 12月 21 13:03 test[root@localhost cpptest]# ./test ljt5
也可胜利生成test。
采纳此种形式,如果咱们在内部调用一个func(str,"5");,仍然会报错,因为未对func(string,string)进行实例化调用,没有生成对应的符号。
模板拆散的解决办法:
1、文件(.h/.cpp)拆散,在cpp中对每种状况进行实例化调用
template<class T1,class T2>void func(T1 t1,T2 t2){ cout<<t1<<t2<<endl;}void func1(string str,int num){ func(str,num);}void func1(string str1,string str2){ func(str1,str2);}void func1(string str1,double dx){ func(str1,dx);}//etc.
2、申明和定义都放到.h中(STL)
相当于在cpp中进行实例化,在.h中实现申明和定义,然而这个违反了拆散编译的思维。
test.h
#include <iostream>using namespace std;template<class T1,class T2>void func(T1 t1,T2 t2);template<class T1,class T2>void func(T1 t1,T2 t2){ cout<<t1<<t2<<endl;}
参考:https://www.cnblogs.com/downe...