C++模板的特化超詳細(xì)精講
一、泛型編程
我們前面已經(jīng)學(xué)過函數(shù)的重載,實(shí)現(xiàn)了在函數(shù)名相同的情況下,實(shí)現(xiàn)不同的功能!
例如:
void Swap(int& left, int& right) { int temp = left; left = right; right = temp; } void Swap(double& left, double& right) { double temp = left; left = right; right = temp; } void Swap(char& left, char& right) { char temp = left; left = right; right = temp; }
利用函數(shù)重載雖然實(shí)現(xiàn)了“通用”的交換函數(shù),但是會(huì)有以下問題:
- 重載的函數(shù)僅僅是類型不同,代碼復(fù)用率低,只要有新的類型時(shí),有需要用戶自己增加新的重載函數(shù)。
- 代碼的可維護(hù)性低,一個(gè)出錯(cuò)可能所有的重載都出錯(cuò)。
??????:在C++中是否存在一個(gè)模具,通過給這個(gè)模具中填充不同的材料(類型),來獲得不同的鑄件(即生成具體的代碼)。
泛型編程:編寫與類型無關(guān)的通用代碼,是代碼復(fù)用的一種的手段。模板是泛型編程的基礎(chǔ)。
二、函數(shù)模板
2.1、函數(shù)模板的概念
函數(shù)模板代表了一個(gè)函數(shù)家族,該函數(shù)模板與類型無關(guān),在使用時(shí)被參數(shù)化,根據(jù)實(shí)參類型產(chǎn)生函數(shù)的特定類型版本。
2.2、函數(shù)模板的格式
template<typename T1, typename T2,…,typename Tn>
返回值類型 函數(shù)名(參數(shù)列表){}
template<typename T> void Swap(T& left, T& right) { T temp = left; left = right; right = temp; }
??注意:typename 是用來定義函數(shù)模板參數(shù)關(guān)鍵字的,也可以用class,但是不可以用struct。
2.3、函數(shù)模板的原理
函數(shù)模板我們可以理解為一個(gè)藍(lán)圖,它本身并不是函數(shù),在編譯器編譯階段根據(jù)傳入的實(shí)參類型來推演生成對(duì)應(yīng)類型的函數(shù)以供調(diào)用,也叫做函數(shù)模板的實(shí)例化。
2.4、函數(shù)模板的實(shí)例化
用不同類型的對(duì)象使用函數(shù)模板時(shí),稱為函數(shù)模板的實(shí)例化。模板參數(shù)實(shí)例化分為隱式實(shí)例化和顯示實(shí)例化。
2.4.1、隱式實(shí)例化
讓編譯器根據(jù)實(shí)參推演模板參數(shù)的實(shí)際類型。
template<class T> T Add(const T& left, const T& right) { return left + right; } int main(){ int a1 = 10, a2 = 20; double d1 = 10.0, d2 = 20.0; Add(a1, a2); Add(d1, d2); //Add(a1, d1); Add(a1, (int)d1); system("pause"); return 0; }
2.4.2、顯示實(shí)例化
讓函數(shù)名后的<>中指定模板參數(shù)的實(shí)際類型。
int main(){ int a = 10; double b = 20.0; //Add(a, (int)b);//隱式 Add<int>(a, b);//顯示 system("pause"); return 0; }
Add(a, b);目的在于如果類型不匹配,編譯器會(huì)嘗試進(jìn)行隱式類型轉(zhuǎn)換,如果無法轉(zhuǎn)換成功編譯器將會(huì)報(bào)錯(cuò)。
三、類模板
3.1、類模板的定義格式
template<typename T1, typename T2,…,typename Tn>
class 類模板名
{
//類內(nèi)成員
};
3.1、類模板的實(shí)例化
類模板實(shí)例化與函數(shù)模板實(shí)例化不同,類模板實(shí)例化傳的是類型,而函數(shù)模板實(shí)例化傳的是對(duì)象,類模板實(shí)例化需要在類模板名字后面跟上<>,然后將實(shí)例化類型放在<>中即可!
vector<int> s1;
??:與普通類不同,這里vector是類名,而vector才是類型。
四、模板的特化
4.1、概念
通常情況下,我們使用模板可以實(shí)現(xiàn)一些與類型無關(guān)的代碼,但是對(duì)于一些特殊類型可能會(huì)得到一些錯(cuò)誤的結(jié)果,需要特殊處理。
template<class T> bool Less(T left, T right){ return left < right; } //特化 template<> bool Less<Date*>(Date* p1, Date* p2) { cout << "調(diào)用的模板函數(shù)的特化" << endl; return *p1 < *p2; } //只要是指針 都可以調(diào)用這個(gè),這個(gè)思想很重要 //偏特化的帶限制條件(指針類型可調(diào)) template<class T> bool Less(T* left, T* right) { cout << "調(diào)用的函數(shù)模板" << endl; return *left < *right; }
代碼解釋:當(dāng)我們?cè)趯?shí)參部分傳的是Date型指針的時(shí)候,如果不特化處理,結(jié)果會(huì)出錯(cuò)。
上述就是在原模板的基礎(chǔ)上針對(duì)特殊類型所進(jìn)行特殊化的實(shí)現(xiàn)方式。模板特化中分為函數(shù)模板特化和類模板特化。
4.2、函數(shù)模板特化步驟
- 必須要先有一個(gè)基礎(chǔ)的函數(shù)模板。
- 關(guān)鍵字template后面接一隊(duì)空的<>。
- 函數(shù)名后跟一對(duì)<>,尖括號(hào)中指定需要特化的類型。
- 函數(shù)形參表:必須要和模板函數(shù)的基礎(chǔ)參數(shù)類型完全相同,如果不同編譯器可能會(huì)報(bào)一些奇怪的錯(cuò)誤。
template<class T> bool Less(T left, T right){ return left < right; } //特化 template<> bool Less<Date*>(Date* p1, Date* p2) { cout << "調(diào)用的模板函數(shù)的特化" << endl; return *p1 < *p2; }
4.3、類模板的特化
4.3.1、全特化
全特化就是將模板參數(shù)中所有的參數(shù)都確定化
//類模板 template<class T1, class T2> class data { public: data(T1 a, T2 b) :_a(a) , _b(b) { cout << "data<T1, T2>" << endl; } private: T1 _a; T2 _b; }; //全特化 template<> class data <int, char> { public: data(int a, char b) :_a(a) , _b(b) { cout << "全特化data<int, char>" << endl; } private: int _a; char _b; }; int main() { data<int, int> s1(1, 2); data<int, char> s2(1, 'a'); }
4.3.2、偏特化
偏特化:任何針對(duì)模板參數(shù)進(jìn)一步進(jìn)行條件限制設(shè)計(jì)的特化版本。比如對(duì)一下類模板:
//類模板 template<class T1, class T2> class data{ public: data(T1 a, T2 b) :_a(a) , _b(b) { cout << "data<T1, T2>" << endl; } private: T1 _a; T2 _b; };
??????偏特化有以下兩種變現(xiàn)方式:
部分特化:將模板參數(shù)中的一部分參數(shù)特化
//半特化 // 1、將模板參數(shù)類表中的一部分參數(shù)特化。 template<class T1> class data<T1, char> { public: data(T1 a, char b) :_a(a) , _b(b) { cout << "偏特化data<T1, char>" << endl; } private: T1 _a; char _b; };
參數(shù)進(jìn)一步限制:偏特化并不僅僅是指特化部分參數(shù),而是針對(duì)模板參數(shù)更進(jìn)一步的條件限制所設(shè)計(jì)出來的特化版本。
// 2、偏特化并不僅僅是指特化部分參數(shù),而是針對(duì)模板參數(shù)更進(jìn)一步的條件限制所設(shè)計(jì)出來的一個(gè)特化版本。 template<class T1, class T2> class data <T1*, T2* > { public: data(T1 a, char b) :_a(a) , _b(b) { cout << "Data<T1*, T2*>" << endl; } private: T1 _a; T2 _b; }; template<class T1, class T2> class data<T1&, T2&> { public: data(const T1& a, const T2& b) :_a(a) , _b(b) { cout << "Data<T1&, T2&>" << endl; } private: const T1& _a; const T2& _b; }; int main(){ data<char*, char*> s6(1,2); data<int&, int&> s7(1, 2); system("pause"); return 0; }
代碼解釋:
- 第一個(gè)是兩個(gè)參數(shù)特例化為指針類型(只要傳的是指針,就走對(duì)應(yīng)的)。
- 第二個(gè)是兩個(gè)參數(shù)特例化為引用類型。
到此這篇關(guān)于C++模板的特化超詳細(xì)精講的文章就介紹到這了,更多相關(guān)C++模板特化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Opencv實(shí)現(xiàn)邊緣檢測(cè)與輪廓發(fā)現(xiàn)及繪制輪廓方法詳解
這篇文章主要介紹了Opencv實(shí)現(xiàn)邊緣檢測(cè)與輪廓發(fā)現(xiàn)及繪制輪廓方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12簡(jiǎn)單講解C++的內(nèi)部和外部函數(shù)以及宏的定義
這篇文章主要介紹了簡(jiǎn)單講解C++的內(nèi)部和外部函數(shù)以及宏的定義,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09C語言鏈表實(shí)現(xiàn)圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言鏈表實(shí)現(xiàn)圖書管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01C++ 網(wǎng)絡(luò)連通性檢測(cè)的實(shí)現(xiàn)方法
這篇文章主要介紹了C++ 網(wǎng)絡(luò)連通性檢測(cè)的實(shí)現(xiàn)方法的相關(guān)資料,這里提供實(shí)例幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09C++實(shí)現(xiàn)大整數(shù)乘法(字符串乘法)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)大整數(shù)乘法、字符串乘法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-09-09C++雙線程調(diào)用網(wǎng)絡(luò)攝像頭與多線程調(diào)用多攝像頭同步執(zhí)行方法詳細(xì)講解
這篇文章主要介紹了C++雙線程調(diào)用網(wǎng)絡(luò)攝像頭與多線程調(diào)用多攝像頭同步執(zhí)行方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-11-11