選擇合肥網(wǎng)站建設(shè)站長之家統(tǒng)計
前言
在前面我們曾經(jīng)簡單的介紹過c++的模板,但還并不全面,我們通過stl容器的學(xué)習(xí)加深了我們對c++這門語言的理解。那么今天我們就再來談一談c++模板,對模板再進行一點簡單的補充
非類型模板參數(shù)
前面我們介紹的是類型模板參數(shù),簡單理解就是把類型當(dāng)做參數(shù)傳遞給類/方法,今天我們第一個要介紹的就是與之對應(yīng)的非類型模板參數(shù)
非類型形參,就是用一個常量作為類(函數(shù))模板的一個參數(shù),在類(函數(shù))模板中可將該參數(shù)當(dāng)成常
量來使用
比如說,我們想在c++中使用可以動態(tài)開辟大小的數(shù)組,就可以使用非類型模板參數(shù)
namespace zzzyh
{// 定義一個模板類型的靜態(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;};
}
如上我們就可以模擬實現(xiàn)一個動態(tài)開辟的數(shù)組
注意,浮點數(shù)、類對象以及字符串是不允許作為非類型模板參數(shù)的,要求在編譯時期確認參數(shù)大小?
模板特化
模板的作用是忽略類型上的不同,抽取共性,復(fù)用同一套邏輯,那么我們現(xiàn)在需要實現(xiàn)一個比較大小的模板,看看會不會有什么意想不到的問題
template<class T>
bool Less(T left, T right)
{return left < right;
}
看起來沒什么問題,但是如果我們想比較兩個地址里的值,用這種模板是有可能是不正確的
int main()
{int b = 20;int a = 10;int* t2 = &b;int* t1 = &a;cout<<Less(t1, t2);return 0;
}
原因很簡單,這里比較的是兩個地址的大小
此時,就需要對模板進行特化。即:在原模板類的基礎(chǔ)上,針對特殊類型所進行特殊化的實現(xiàn)方
式。模板特化中分為函數(shù)模板特化與類模板特化
函數(shù)模板特化
函數(shù)模板的特化步驟:
1. 必須要先有一個基礎(chǔ)的函數(shù)模板
2. 關(guān)鍵字template后面接一對空的尖括號<>
3. 函數(shù)名后跟一對尖括號,尖括號中指定需要特化的類型
4. 函數(shù)形參表: 必須要和模板函數(shù)的基礎(chǔ)參數(shù)類型完全相同,如果不同編譯器可能會報一些奇
怪的錯誤
template<>
bool Less<int*>(int* left, int* right)
{return *left < *right;
}
此時程序會自動調(diào)用特化之后的版本,而不走模板生成了
一般情況下如果函數(shù)模板遇到不能處理或者處理有誤的類型,為了實現(xiàn)簡單通常都是將該
函數(shù)直接給出,不走模板特化的邏輯,比較推薦這種做法
類模板特化
全特化
全特化即是將模板參數(shù)列表中所有的參數(shù)都確定化
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;
};void TestVector()
{Data<int, int> d1;Data<int, char> d2;
}
偏特化
偏特化是與全特化相對的概念,其特點是特化部分參數(shù),其中細分又可以分為指定具體的類型或者是像T*/T&這樣的類型
部分特化
將模板參數(shù)類表中的一部分參數(shù)特化
template <class T1>
class Data<T1, int>
{ public:Data() {cout<<"Data<T1, int>" <<endl;}private:T1 _d1;int _d2;
};
特定類型
//兩個參數(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;
};
模板分離編譯
一個程序(項目)由若干個源文件共同實現(xiàn),而每個源文件單獨編譯生成目標(biāo)文件,最后將所有
目標(biāo)文件鏈接起來形成單一的可執(zhí)行文件的過程稱為分離編譯模式
我們推薦將.cpp文件和.h文件分離開來,因為這會使工程項目一目了然
但是模板的聲明與定義分離開,在頭文件中進行聲明,源文件中完成定義,,在連接時會報錯
為了解決這個問題,我們一般將聲明和定義放到一個文件 "xxx.hpp" 里面或者xxx.h其實也是可以的。推薦使用這種。
當(dāng)然也可以在模板定義的位置顯式實例化,不常用這種方法
結(jié)語
以上便是今天的全部內(nèi)容。如果有幫助到你,請給我一個免費的贊。
因為這對我很重要。
編程世界的小比特,希望與大家一起無限進步。
感謝閱讀!