C++ 初识模板
目錄
泛型編程
函數(shù)模板
類模板
非類型模板參數(shù)
?
-
泛型編程
若我們要寫一個(gè)swap交換函數(shù),當(dāng)交換的兩個(gè)變量為int型,swap函數(shù)的參數(shù)類型為int;當(dāng)交換的兩個(gè)變量為double型,那么就要重載一個(gè)swap函數(shù),參數(shù)變?yōu)閐ouble型。若出現(xiàn)新類型時(shí),就需要增加對(duì)應(yīng)的函數(shù)。這樣就使得代碼的可維護(hù)性變低,一出錯(cuò)可能所有的重載均出錯(cuò)。
要解決上面這個(gè)問(wèn)題我們就要用到一種手段:模板。
泛型編程:編寫與類型無(wú)關(guān)的通用代碼,是代碼復(fù)用的一種手段。模板是泛型編程的基礎(chǔ)。
模板又分為:函數(shù)模板、類模板。
?
-
函數(shù)模板
函數(shù)模板代表了一個(gè)函數(shù)家族,該函數(shù)模板與類型無(wú)關(guān),在使用時(shí)被參數(shù)化,根據(jù)實(shí)參類型產(chǎn)生函數(shù)的特定類型版本。
格式為:
? ? ? ? ? ? template<typename T1,....typename T2,typename T3>?(typename可以換為class,但不能使用struct代替class)
? ? ? ? ? ? 返回值類型 函數(shù)名(參數(shù)列表){}
//模板并不是函數(shù),是編譯器用使用方式產(chǎn)生的具體類型函數(shù)的摸具 //編譯階段,編譯器根據(jù)傳入的實(shí)參類型來(lái)推演生成相對(duì)應(yīng)的函數(shù)。 template<class T> void swap(T& a,T& b) {T tmp = a;a = b;b = tmp; } int main() {int a=0, b=1;double c=2.2, d=3.3;swap(a,b);swap(c,d); //兩者沒(méi)有調(diào)同一個(gè)swap,仍舊存在兩個(gè)swap,由編譯器生成 }函數(shù)模板的實(shí)例化就是用不同類型的參數(shù)使用函數(shù)模板。它又分為:隱式實(shí)例化、顯示實(shí)例化。
隱式實(shí)例化:讓編譯器根據(jù)實(shí)參推演模板參數(shù)的實(shí)際類型。
上述例子中若加一句 swap(a, c),這是不能通過(guò)編譯的。因?yàn)榫幾g期間,編譯器看到該實(shí)例化時(shí),需要推演其 實(shí)參類型。通過(guò)a將T推演為int,通過(guò)c將T推演為double,但模板參數(shù)列表只有一個(gè)T,所以編譯器無(wú)法確定T的類型而報(bào)錯(cuò)。
如果非要執(zhí)行這句代碼,那要怎么辦呢?
? ? ?1.強(qiáng)轉(zhuǎn):swap(a, (int)c);
? ? ?2.使用? 顯示實(shí)例化
顯示實(shí)例化:在函數(shù)名后的<>中指定模板參數(shù)的實(shí)際類型
上面的那句代碼就可以改為:swap<int>(a, c);
若類型不匹配,編譯器會(huì)嘗試進(jìn)行隱式類型轉(zhuǎn)換,如果無(wú)法轉(zhuǎn)換成功編譯器將會(huì)報(bào)錯(cuò)。
?
函數(shù)模板的匹配原則:
1.一個(gè)非模板函數(shù)可以和一個(gè)同名參數(shù)模板同時(shí)存在,而且該函數(shù)模板可以被實(shí)例化為這個(gè)非函數(shù)模板
2.如果非模板函數(shù)和模板函數(shù)條件相同,優(yōu)先使用非模板函數(shù),如果模板函數(shù)可以產(chǎn)生一個(gè)更好的匹配函數(shù),那將選擇模板
3.顯示指定一個(gè)空的模板實(shí)參列表,該語(yǔ)法告訴編譯器自由模板才能匹配這個(gè)調(diào)用,而且所有的模板參數(shù)都應(yīng)該根據(jù)實(shí)參演繹出來(lái)
4. 模板函數(shù)不允許自動(dòng)類型轉(zhuǎn)換,但普通函數(shù)可以進(jìn)行自動(dòng)類型轉(zhuǎn)換
看看下面的測(cè)試代碼:
// 1.專門處理int的加法函數(shù) int Add(int left, int right) { return left + right; }// 2.通用加法函數(shù) template<class T> T Add(T left, T right) { return left + right; }// 3.通用加法函數(shù) template<class T1, class T2> T1 Add(T1 left, T2 right) { return left + right; }void Test() { Add(1, 2); // 調(diào) 1Add<int>(1, 2); // 調(diào) 2Add(1, 2.0); // 調(diào) 3 Add<>(1, 2); // 調(diào) 2 }?
-
類模板
? ? ? ? 格式:
template<class T1,class T2,……class Tn> class 模板名 {//類成員變量 }? ? ? ? 例:
//實(shí)現(xiàn)一個(gè)簡(jiǎn)單的動(dòng)態(tài)順序表 //Vector不是具體的類,是編譯器根據(jù)被實(shí)例化的類型生成具體類的模具template<class T> class Vector { private:T * _pdata;int _size;int _capacity;public:Vector(size_t capacity):_pdata(new T[capacity]), _size(0), _capacity(capacity){}void PushBack(const T& data) { _pData[_size++] = data; }void popback(){--_size;}~Vector(); };// 注意:類模板中函數(shù)放在類外進(jìn)行定義時(shí),需要加模板參數(shù)列表 template <class T> Vector<T>::~Vector() { if(_pData) { delete[] _pData;} }類模板的實(shí)例化 :類模板實(shí)例化需要在類模板名字后跟<>,然后將實(shí)例化的類型放在<> 中即可,類模板名字不是真正的類,而實(shí)例化的結(jié)果才是真正的類。
例:
Vector<int> s1;
Vector<double> s2;?
?
-
非類型模板參數(shù)
就是用一個(gè)常量作為類(函數(shù))模板的一個(gè)參數(shù),在類(函數(shù))模板中可將該參數(shù)當(dāng)成常量來(lái)使用。
template<class T, size_t N = 10> class Array { private: T _array[N]; size_t _size; };注意:
1. 大部分非類型模板參數(shù)都是整形,浮點(diǎn)數(shù)、類對(duì)象以及字符串不能作為非類型模板參數(shù)的。
2. 非類型的模板參數(shù)必須在編譯期就能確認(rèn)結(jié)果。
?
總結(jié)
- 上一篇: C++中引用的一些问题
- 下一篇: C++ 模板特化