模板特化
class A{
public:
void func1();
void func2();
};
class B{
public:
void func1();
void func2();
};
template<typename company>
class manager{
public:
void dofun1()
{
company c;
c.fun1();
}
void dofun2()
{...}
};
template<typename company>
class bettermanager : public manager<company>{
public:
void dobetterfun1()
{
dofun1();//調用模板化基類:manager<company>的函數,無法通過編譯
}
};
問題在於,當編譯器遇到bettermanager類的定義式時,由於不知道模板化基類manager< company >中的模板參數company 的值,因此不知道繼承的是什麼樣的class,就無法知道manager< company >是否有dofun1函數。
比如說:
class C{
public:
void func2();
};
//一個針對類型C特化的manager,而且特化是全面性的,也就是說一旦類型參數被定義爲C,再沒有其他模板參數可供變化
template<>
class manager<C>{
public:
void dofun2(){...}
};
此時的bettermanager代碼中,如果class bettermanager : public manager< company >的company是C,manager< C >模板化基類沒有dofun1函數。
因此C++拒絕這個調用的原因:它知道base class template(manager< company >)有可能被特化(C),而那個特化版可能不提供和一般性template相同的接口。
模板參數造成的代碼膨脹(代碼膨脹=相同部分的重複)
兩個函數或類中的某些部分的實現碼實質相同時,可以抽出兩個函數或類中共同部分,放進新的函數或類,然後令兩個函數調用新函數或使用繼承或複合取用新類。但是在模板代碼中,重複是隱晦的:畢竟只存在一份模板源碼,所以必須訓練自己去感受當模板被具體實現化多次時可能發生的重複。
template<typename T,std::size_t n>//n爲非類型模板參數,T爲類型模板參數
class A{...};
Template生成多個classes與多個函數,所以任何template代碼都不該與某個造成膨脹的template參數產生相依關係。
- 因非類型模板參數而造成的代碼膨脹,往往可以消除,做法是以函數參數或者class成員變量替換template參數。
- 因類型參數而造成的代碼膨脹,也可以降低,做法是讓帶有完全相同二進制表述的具現類型共享實現碼。