内联函数不能为虚函数,原因在于虚表机制需要一个真正的函数地址,而内联函数展开以后,就不是一个函数,
而是一段简单的代码,可能有些内联函数会无法内联展开,而编译成为函数
虚函数不能模板化
编译器在编译一个类的时候,需要确定这个类的虚函数表的大小。一般来说,如果一个类有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; };
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/17548.html