參考:http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file
在 C++ 中定義普通的類的時候,比較清晰和普遍的做法是在 .h 文件中聲明類的接口,如果有 inline 函數也一并放在 .h 中的 class 關鍵字中。然后在 .cpp 文件中實現 .h 中聲明的接口。
在定義模板類時,如果要將接口與實現分離會略有不同。如果把模板類的實現像普通類一樣放在 .cpp 文件中鏈接器會報錯。
有兩個方法可以實現模板類的接口和實現在文件中的分離:
一個前提
“類模板的成員函數是一個普通函數。但是類模板的每個實例都有其自己版本的成員函數。因此類模板的成員函數具有和模板相同的模板參數。因此定義在類模板之外的成員函數就必須以關鍵字 template 開始,后接類模板參數列表?!?br> ——《C++ Primer》中文版,第五版,P585
使用 .tpp 文件實現類模板的接口與實現的文件分離
比如說有這樣一個模板類,這是它的接口:
template <typename Node>
class TestTemplate{
public:
TestTemplate(Node node):
data(node) { }
Node data;
void print();
};
這是它的實現:
template <typename node>
void TestTemplate<node>::print(){
std::cout << "TestTemplate " << data << std::endl;
}
如果把它們分別放在 .h 和 .cpp 文件中,鏈接器會報錯,提示找不到實現。
在 .h 文件中模板類的實現下加這一句:
#include "TestTemplate.tpp"
然后把實現放在名為 TestTemplate.tpp 文件中,即可。
使用顯式聲明實現類模板的接口與實現的文件分離
假設上面那個類的接口與實現分別放在了 .h 和 .cpp 文件中。然后在 .cpp 文件中顯式的聲明要使用的模板類實例,比如:
template class TestTemplate<int>;
然后,使用 TestTemplate<int> 也可以通過編譯鏈接,但是只能使用已經顯式聲明的模板類實例。比如如果還要使用 TestTemplate<float>,就要這樣:
template class TestTemplate<int>;
template class TestTemplate<float>;
就是說只能只用已經顯式聲明過的模板類實例。