對于編譯器而言,編譯器不對模闆本身進行檢查,會對執行個體化後的代碼進行檢查。
函數模闆;
模闆的比對原則:
有現成的就用現成的(現在人的思維)
沒有現成的就用模闆,如果非要用模闆,就用顯示定義的方法。
類模闆:
使用函數重載可以實作,但是有不好的地方。
1.重載的函數僅僅隻是類型不同,代碼的複用率比較低,隻要有新類型出現時,就需要增加對應的函數
2.代碼的可維護性比較低,一個出錯可能所有的重載均出錯
函數模闆概念:
函數模闆代表了一個函數家族,該函數模闆與類型無關,在使用時被參數化,根據實參類型産生函數的特定類型版本
函數模闆格式
template<typename T1,typename T2,…typename Tn>
傳回值類型 函數名(參數清單){}
template<typename T>
void Swap(T& left,T& right)
{
T temp=left;
left=right;
right=temp
}
typename是用來定義模闆參數關鍵字,也可以用class(不能用struct代替class)
在編譯器編譯階段,對于模闆函數的使用,編譯器需要根據傳入的實參類型來推演生成對應類型的函數以供調用,當用double類型使用函數模闆時,編譯器通過對實參類型的推演,将T确定為double類型。
**函數模闆的執行個體化**
用不同類型的參數使用函數模闆時,稱為函數模闆的執行個體化。模闆參數執行個體化分為:隐式執行個體化和顯示執行個體化
1.隐式執行個體化:讓編譯器根據實參推演模闆參數的實際類型
template
T Add(const T&left,const T&right)
{
return left+right;
}
2.顯示執行個體化:在函數名後的<>中指定模闆參數的實際類型
int main(void)
{
int a=10;
double b=20.0;
//顯示執行個體化
Add (a,b);
return 0;
}
**模闆參數的比對原則**
1.一個非模闆函數可以和一個同名的函數模闆同時存在,而且該函數模闆還可以被執行個體化為這個非模闆函數
//專門處理int 的加法函數
int Add(int left,int right)
{
return left+right;
}
//通用加法函數
template<class T>
T Add(T left, T right)
{
return left+right;
}
void Test()
{
Add(1,2);
Add<int>(1,2);
}
2.對于非模闆函數和同名函數模闆,在調用時會調用非模闆函數而不會從該模闆産生出一個執行個體,如果模闆可以産生一個具有更好比對的函數,
//專門處理int的加法函數
int Add(int left,int right)
{
return left+right;
}
//通用加法函數
template<class T
1,class T2
>
T1 Add(T1 left,T2 right)
{
return left+right;
}
void Test()
{
Add(1,2);//與非函數模闆類型完全比對,不需要函數模闆執行個體化
Add(1,2.0);//函數模闆可以生成更加比對的版本,編譯器根據實參生成更加比對的Add函數
}
3.模闆函數不允許自動類型轉換,但普通函數可以進行自動類型轉換
**類模闆**
類模闆的定義格式
類模闆的執行個體化
類模闆執行個體化與函數模闆執行個體化不同,類模闆執行個體化需要在類模闆名字後跟<>,然後将執行個體化的類型放在<>中即可,類模闆名字不是真正的類,而執行個體化的結果才是真正的類