1、模板聲明和模板定義如果不在同一個文件中,在另一個文件中使用模板時會出現鏈接錯誤。
例子:
//Myfirst.h
#ifndef MYFIRST_H
#define MYFIRST_H
#include<iostream>
#include<typeinfo>
using namespace std;
template<typename T>
void print_typeof(T const& x);
#endif
//Myfirst.cpp
#include"Myfirst.h"
#include<iostream>
#include<typeinfo>
using namespace std;
template<typename T>
void print_typof(T const& x){
cout << typeid(x).name() << endl;
}
//main.cpp
#include"Myfirst.h"
int main(){
double ice = 3.0;
print_typeof(ice);
system("pause");
return 0;
}
原因:函數模板print_typeof()的定義還沒有被實例化。當實例化一個模板時,編譯器必須知道應該實例化哪個定義及要基於哪個模板實參進行實例化。編譯器在MyFirst.h文件中看到了模板的聲明,但沒有模板的定義,這樣編譯器就不能創建voidprint_typof(double const& x),但這時並不出錯,因爲編譯器認爲模板定義在其它文件中,併產生一個指向該定義的引用,讓鏈接器利用該引用解決這個問題。
2、解決以上問題可以有以下幾種方法:
2.1、包含模型:把模板的定義包含在聲明模板的頭文件裏
//Myfirst.h
#ifndef MYFIRST_H
#define MYFIRST_H
#include<iostream>
#include<typeinfo>
using namespace std;
template<typename T>
void print_typeof(T const& x);
template<typename T>
void print_typeof(T const& x){
cout << typeid(x).name() << endl;
}
#endif
//main.cpp
#include"Myfirst.h"
int main(){
double ice = 3.0;
print_typeof(ice);
system("pause");
return 0;
}
包含模型的缺點:a、增加了頭文件的開銷 b、大大增加了編譯複雜程序所耗費的時間
2.2、顯示實例化
在1的基礎上,添加MyFirstinst.cpp
//Myfirst.h
#ifndef MYFIRST_H
#define MYFIRST_H
template<typename T>
void print_typeof(T const& x);
#endif
//Myfirst.cpp
#include"Myfirst.h"
#include<iostream>
#include<typeinfo>
using namespace std;
template<typename T>
void print_typeof(T const& x){
cout << typeid(x).name() << endl;
}
//Myfirstinst.cpp
#include"Myfirst.cpp"
template void print_typeof<double>(double const& x);
//main.cpp
#include"Myfirst.h"
#include<iostream>
using namespace std;
int main(){
double ice = 3.0;
print_typeof(ice);
system("pause");
return 0;
}
2.3、分離模型:在模板定義和聲明前加上關鍵字export
如函數模板聲明:
//Myfirst.h
#ifndef MYFIRST_H
#define MYFIRST_H
export template<typename T>
void print_typeof(T const& x);
#endif
但VS 2013編譯器還不支持。