內聯函數不能為虛函數,原因在於虛表機制需要一個真正的函數地址,而內聯函數展開以后,就不是一個函數,
而是一段簡單的代碼,可能有些內聯函數會無法內聯展開,而編譯成為函數
虛函數不能模板化
編譯器在編譯一個類的時候,需要確定這個類的虛函數表的大小。一般來說,如果一個類有N個虛函數,它的虛函數表的大小就是N,如果按字節算的話那么就是4*N。
如果允許一個成員模板函數為虛函數的話,因為我們可以為該成員模板函數實例化出很多不同的版本,也就是可以實例化出很多不同版本的虛函數,那么編譯器為了確定類的虛函數表的大小,就必須要知道我們一共為該成員模板函數實例化了多少個不同版本的虛函數。顯然編譯器需要查找所有的代碼文件,才能夠知道到底有幾個虛函數,這對於多文件的項目來說,代價是非常高的,所以規定成員模板函數不能夠為虛函數。
那么編譯器在編譯Func類的時候,需要查看int mian 里面的具體調用,才知道會產生兩個虛函數。一個是virtual int Add (const int &a, const int &b); 另一個是 virtual double Add (const double &a, const double &b)。當項目很大,文件特別多的時候,需要遍歷完所有的文件才能確定實際會產生多少虛函數,所以這樣編譯的效率會非常的低。因此規定成員模板函數不能夠為虛函數
最近要修改一個模板類的功能,對於特定形式的參數,想要復用函數名,進入不同的路徑,於是就想到了模板函數偏特化
舉個例子
#include <iostream> using namespace std; template <class T> class A { public: template <class T2> void Func(T2 t) { cout << t; } //成員函數模板 template <> void Func<int>(int t) { cout << t; } //特化int }; int main() { A<int> a; a.Func('K'); //成員函數模板Func被實例化 a.Func("hello"); return 0; }
此處遇到了幾個問題
1.類模板的模板函數,必須要在類內部定義,不然在外部template都不知道是類的還是函數的
如果相對只想對模板類的某個函數偏特化,要用以下寫法
template<typename DataKey, typename Data> class CTemplateReportDataBaseMgr { public: bool print1( Data out_map_report_data, std::vector<DataKey>& in_vt_data_key) ; }; template<typename DataKey, typename Data> bool CTemplateReportDataBaseMgr<DataKey, Data>::print1( Data out_map_report_data, std::vector<DataKey>& in_vt_data_key) { return true; }; template<> bool CTemplateReportDataBaseMgr<class DataKey,int>::print1( //注意這里的寫法,不能直接像偏特化類一樣的寫法 int out_map_report_data, std::vector<DataKey>& in_vt_data_key) { return true; };
類的模板特化寫法
template<typename T1,typename T2> class Test{ public: Test(T1 i,T2 j):a(i),b(j){cout<<"模板類"<<endl;} private: T1 a; T2 b; }; template<> //全特化,由於是全特化,參數都指定了,參數列表故為空。 class Test<int ,char>{ public: Test(int i,char j):a(i),b(j){cout<<"全特化"<<endl;} private: int a; int b; }; template<typename T2> //由於只指定了一部分參數,剩下的未指定的需在參數列表中,否則報錯。 class Test<char,T2>{ public: Test(char i,T2 j):a(j),b(j){cout<<"個數偏特化"<<endl;} private: char a; T2 b; };