文化網(wǎng)站建設(shè)論文寧德市人民政府
一、非類型模版參數(shù)
之前學(xué)習(xí)的模版,參數(shù)一般是某種類型,但其實(shí)非類型的參數(shù)也可以定義在模版里面,但也有一定的限制,只可以定義整形家族的參數(shù),而且具有常量性
注意:
1. 浮點(diǎn)數(shù)、類對象以及字符串是不允許作為非類型模板參數(shù)的。
2. 非類型的模板參數(shù)必須在編譯期就能確認(rèn)結(jié)果。
namespace chk
{// 定義一個模板類型的靜態(tài)數(shù)組template<class T, size_t N = 10>class array{public:T& operator[](size_t index){return _array[index];}const T& operator[](size_t index)const{return _array[index];}size_t size()const{return _size;}bool empty()const{return 0 == _size;}private:T _array[N];size_t _size;};
}
二、模板的特化
1.概念
模板的特化是針對一些較為特殊的情況,可以針對模板的某一種或者某一類實(shí)例化去進(jìn)行特殊的處理,在某些場景下會特別方便
例如,在使用堆時若是想傳指針,實(shí)際想比較的是指針?biāo)赶虻膬?nèi)容時,可以對模版進(jìn)行特化,在針對傳模板參數(shù)為兩個指針時進(jìn)行特殊處理
// 函數(shù)模板 -- 參數(shù)匹配
template<class T>
bool Less(T left, T right)
{return left < right;
}
// 對Less函數(shù)模板進(jìn)行特化
template<>
bool Less<Date*>(Date* left, Date* right)
{return *left < *right;
}
int main()
{cout << Less(1, 2) << endl;Date d1(2022, 7, 7);Date d2(2022, 7, 8);cout << Less(d1, d2) << endl;Date* p1 = &d1;Date* p2 = &d2;cout << Less(p1, p2) << endl; // 調(diào)用特化之后的版本,而不走模板生成了return 0;
}
2.特化
特化分為全特化和偏特化,其目的都是為了對模版部分實(shí)例化,根據(jù)不同的要求進(jìn)行特殊的處理
特化的格式是:
對需要進(jìn)行特化處理的部分參數(shù),在template列表里不寫,不進(jìn)行特化的照寫,到函數(shù)名后一一對應(yīng),將特化的部分給具體值或者類型,不特化的部分照寫模板,例如:
template<class T,class U,char N>
class chk
{//...
}//全特化
template<>
class chk<int,double,5>
{//...
}//偏特化U為int
template<class T,char N>
class chk<T,int,N>
{//...
}
(1)全特化
全特化是指模板參數(shù)全確定的情況下,進(jìn)行特殊處理,對所有模板參數(shù)都進(jìn)行特化
template<class T1, class T2>
class Data
{
public:Data() {cout<<"Data<T1, T2>" <<endl;}
private:T1 _d1;T2 _d2;
};template<>
class Data<int, char>
{
public:Data() {cout<<"Data<int, char>" <<endl;}
private:int _d1;char _d2;
};
(2)偏特化
在部分情況下會需要針對某一種具體的情況進(jìn)行處理,可以用全特化,而往往過多的可以是針對某一類情況進(jìn)行特殊處理,偏特化的范圍是比全特化的范圍更大的
偏特化也分兩種方式,一種是部分特化,一種是將模板參數(shù)進(jìn)一步的限制,舉個例子
template<class T1, class T2>
class Data
{
public:Data() {cout<<"Data<T1, T2>" <<endl;}
private:T1 _d1;T2 _d2;
};
這是用來給下面兩種特化做對比舉例的類
部分特化
將部分模板參數(shù)特化成具體的類型或者常量,例如:
// 將第二個參數(shù)特化為int
template <class T1>
class Data<T1, int>
{
public:Data() {cout<<"Data<T1, int>" <<endl;}
private:T1 _d1;int _d2;
};
對參數(shù)進(jìn)一步限制
例如你穿過來的是指針或者是引用,則會走特化的那一塊,這種特化的格式要注意,template里的參數(shù)不能省略
//兩個參數(shù)偏特化為指針類型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:Data() {cout<<"Data<T1*, T2*>" <<endl;}private:T1 _d1;T2 _d2;
};//兩個參數(shù)偏特化為引用類型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:Data(const T1& d1, const T2& d2): _d1(d1), _d2(d2){cout<<"Data<T1&, T2&>" <<endl;}private:const T1 & _d1;const T2 & _d2; };
三、模板的分離編譯
模板通常不支持將聲明和定義放在兩個文件中進(jìn)行編譯,其原因是在鏈接前,兩個文件分別進(jìn)行預(yù)處理,編譯,匯編,最后再鏈接,在編譯階段,由于模板的定義與聲明分離,在定義部分并不會完成模板的實(shí)例化,也就無法具體的對類或函數(shù)里的內(nèi)容進(jìn)行編譯,而在聲明部分則是由于存在聲明,依然通過了編譯階段,到了鏈接時,由于定義的部分未被實(shí)例化,因此找不到具體的地址去執(zhí)行相關(guān)的函數(shù),因此會出現(xiàn)鏈接錯誤
可以使用顯示實(shí)例化解決,但這種方式并不推薦
通常我們選擇將聲明和定義放到同一個文件當(dāng)中,較短的定義直接在類里面定義,較長的可以選擇在類里面聲明,在類外面(同一個文件中)定義。
四、模板的優(yōu)缺點(diǎn)總結(jié)
【優(yōu)點(diǎn)】
1. 模板復(fù)用了代碼,節(jié)省資源,更快的迭代開發(fā),C++的標(biāo)準(zhǔn)模板庫(STL)因此而產(chǎn)生
2. 增強(qiáng)了代碼的靈活性
【缺陷】
1. 模板會導(dǎo)致代碼膨脹問題,也會導(dǎo)致編譯時間變長
2. 出現(xiàn)模板編譯錯誤時,錯誤信息非常凌亂,不易定位錯誤