C++ 深入淺出探索模板
非類型模板參數(shù)
模板參數(shù)分類類型形參與非類型形參。
類型形參:出現(xiàn)在模板參數(shù)列表中,跟在class或者typename之類的參數(shù)類型名稱。
非類型形參,就是用一個常量作為類(函數(shù))模板的一個參數(shù),在類(函數(shù))模板中可將該參數(shù)當(dāng)成常量來使用。
注意:
- 浮點(diǎn)數(shù),類對象以及字符串是不允許作為非類型模板的。
- 非類型的模板參數(shù)必須在編譯期就能確認(rèn)結(jié)果。
模板特化
有時(shí)候,編譯默認(rèn)函數(shù)模板或者類模板不能正確處理需要邏輯,需要針對一些情況特殊化處理,就要做模板特化。
通常情況下,使用模板可以實(shí)現(xiàn)一些與類型無關(guān)的代碼,但對于一些特殊類型的可能會得到一些錯誤的結(jié)果,例如:
template<class T> bool IsEqual(const T&left,const T&right) { return left==right; } //針對字符串類型要特殊化處理--寫一份函數(shù)模板的特殊化出來 template<> bool IsEqual<char*>(const char* &left,const char* &right) { return strcmp(left,right)==0; } ? int main() { cout<<IsEqual(1,2)<<endl;//0 cout<<IsEqual(1.1,1.1)<<endl;//1 char p1[]="hello"; char p2[]="hello"; cout<<IsEqual(p1,p2)<<endl;//0 const char* p3="hello"; const char* p4="hello"; cout<<IsEqual(p3,p4)<<endl;//1 }
此時(shí),就需要對模板進(jìn)行特化。即:在原模板類的基礎(chǔ)上,針對特殊類型所進(jìn)行特殊化的實(shí)現(xiàn)方式。模板特化中分為函數(shù)模板特化與類模板特化。
特化的本質(zhì):顯示指定實(shí)例化的模板
函數(shù)模板特化
函數(shù)模板特化步驟
- 必須要先有一個基礎(chǔ)的函數(shù)模板
- 關(guān)鍵字template后面接一對空的尖括號<>
- 函數(shù)名后跟一對尖括號,尖括號中指定需要特化的類型
- 函數(shù)形參表: 必須要和模板函數(shù)的基礎(chǔ)參數(shù)類型完全相同,如果不同編譯器可能會報(bào)一些奇怪的錯誤
template<> bool IsEqual<const char* const>(const char* const &left,const char* &right) { if(strcmp(left,right)>0) return true; return false; }
注意:一般情況下如果函數(shù)模板遇到不能處理或者處理有誤的類型,為了實(shí)現(xiàn)簡單通常都是將該函數(shù)直接給出。
類模板特化
全特化
全特化既是將模板參數(shù)列表中所有的參數(shù)都確定化
template<calss 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; }; void TestVector() { Data<int,int>d1; Data<int,char>d2; }
偏特化
針對任何模板參數(shù)進(jìn)一步進(jìn)行條件限制設(shè)計(jì)的特化版本,比如對于一下模板類:
template<class T1,class T2> class Data { public: Data(){cout<<"Data<T1,T2>"<<endl;} private: T1 _d1; T2 _d2; }; //偏特化有以下兩種表現(xiàn)方式: //1、部分特化:將函數(shù)中的一部分參數(shù)特化。 ? template<class T1> class Data<T1,int> { public: Data(){cout<<"Data<T1,int>"<<endl;} private: T1 _d1; int _d2; } //2、參數(shù)進(jìn)一步的限制:偏特化并不僅僅是指特化部分參數(shù),而是針對模板參數(shù)更進(jìn)一步的條件限制所設(shè)計(jì)出來的一個特化版本 //兩個參數(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(){cout<<"Data<T1&,T2&>"<<endl;} private: const T1& _d1; const T2& _d2; }; ? void test2() { Data<double,int>d1; //調(diào)用特化的int版本 Data<int,double>d2; //調(diào)用基礎(chǔ)模板 Data<int *,int*>d3; //調(diào)用特化的指針版本 Data<int&,int&>d4(1,2); //調(diào)用特化的引用版本 }
模板分離編譯
分離編譯就是指一個程序由若干個源文件共同實(shí)現(xiàn),而每個源文件單獨(dú)編譯生成目標(biāo)文件,最后將目標(biāo)文件連接起來形成單一的可執(zhí)行文件的過程稱為分離編譯模式。
模板的分離編譯
// a.h template<class T> T Add(const T& left, const T& right); // a.cpp template<class T> T Add(const T& left, const T& right) { return left + right; } // main.cpp #include"a.h" int main() { Add(1, 2); Add(1.0, 2.0); return 0; }
分析:
解決方法
- 將聲明和定義放到一個文件中。推薦使用
- 模板定義的位置顯示實(shí)例化。不實(shí)用
總結(jié)
優(yōu)點(diǎn)
- 模板復(fù)用了代碼,節(jié)省資源,更快的迭代開發(fā),C++的標(biāo)準(zhǔn)模板庫(STL)因此而生
- 增強(qiáng)了代碼的靈活性
缺點(diǎn)
- 模板會導(dǎo)致代碼膨脹問題,也會導(dǎo)致編譯時(shí)間變長。
- 出現(xiàn)模板編譯錯誤時(shí),錯誤信息非常雜亂,不易定位錯誤。
到此這篇關(guān)于C++ 深入淺出探索模板的文章就介紹到這了,更多相關(guān)C++ 模板內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入二叉樹兩個結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
本篇文章是對二叉樹兩個結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05關(guān)于嘗試開發(fā)PHP的MYSQL擴(kuò)展的使用
本篇文章小編將為大家介紹,關(guān)于嘗試開發(fā)PHP的MYSQL擴(kuò)展的使用,需要的朋友可以參考一下2013-04-04C語言結(jié)構(gòu)體嵌套與對齊超詳細(xì)講解
這篇文章主要介紹了C語言結(jié)構(gòu)體嵌套與對齊,C語言中結(jié)構(gòu)體是一種構(gòu)造類型,和數(shù)組、基本數(shù)據(jù)類型一樣,可以定義指向該種類型的指針。結(jié)構(gòu)體指針的定義類似其他基本數(shù)據(jù)類型的定義2022-12-12C語言如何實(shí)現(xiàn)Unix時(shí)間戳與本地時(shí)間轉(zhuǎn)化
這篇文章主要介紹了C語言如何實(shí)現(xiàn)Unix時(shí)間戳與本地時(shí)間轉(zhuǎn)化的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03C語言編程中從密碼文件獲取數(shù)據(jù)的函數(shù)總結(jié)
這篇文章主要介紹了C語言編程中從密碼文件獲取數(shù)據(jù)的函數(shù)總結(jié),包括getpw()函數(shù)和getpwnam()函數(shù)以及getpwuid()函數(shù),需要的朋友可以參考下2015-08-08