柚子快報(bào)邀請(qǐng)碼778899分享:C++:模版初階
柚子快報(bào)邀請(qǐng)碼778899分享:C++:模版初階
目錄
一、泛型編程
二、函數(shù)模版
概念
格式
原理
?實(shí)例化
模版參數(shù)的匹配原則?
三、類模版
定義格式
實(shí)例化
一、泛型編程
? ??如何實(shí)現(xiàn)一個(gè)通用的交換函數(shù)呢?
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),但是有一下幾個(gè)不好的地方:
1. 重載的函數(shù)僅僅是類型不同,代碼復(fù)用率比較低,只要有新類型出現(xiàn)時(shí),就需要用戶自己增 加對(duì)應(yīng)的函數(shù)
2. 代碼的可維護(hù)性比較低,一個(gè)出錯(cuò)可能所有的重載均出錯(cuò) ?
?
?如果在C++中,也能夠存在這樣一個(gè)模具,通過給這個(gè)模具中填充不同材料(類型),來獲得不同材料的鑄件(即生成具體類型的代碼),那將會(huì)節(jié)省許多頭發(fā),巧的是前人早已將樹栽好,我們只 需在此乘涼。
泛型編程:編寫與類型無關(guān)的通用代碼,是代碼復(fù)用的一種手段。模板是泛型編程的基礎(chǔ)。
?
二、函數(shù)模版
概念
? ? ?所謂模板,實(shí)際上是建立一個(gè)通用函數(shù)或類,其類內(nèi)部的類型和函數(shù)的形參類型不具體指定,用一個(gè)虛擬的類型來代表,這種通用的方式稱為模板,函數(shù)模板代表了一個(gè)函數(shù)家族,該函數(shù)模板與類型無關(guān),在使用時(shí)被參數(shù)化,根據(jù)實(shí)參類型產(chǎn)生 函數(shù)的特定類型版本。?
格式
template
返回值類型 函數(shù)名(參數(shù)列表){}
template
void Swap( T& left, ?T& right)
{
T temp = left;
left = right;
right = temp;
}
注意:typename是用來定義模板參數(shù)關(guān)鍵字,也可以使用class(切記:不能使用struct代替 class) ?
原理
? ? 函數(shù)模板是一個(gè)藍(lán)圖,它本身并不是函數(shù),是編譯器用使用方式產(chǎn)生特定具體類型函數(shù)的模具。 所以其實(shí)模板就是將本來應(yīng)該我們做的重復(fù)的事情交給了編譯器
? ??在編譯器編譯階段,對(duì)于模板函數(shù)的使用,編譯器需要根據(jù)傳入的實(shí)參類型來推演生成對(duì)應(yīng) 類型的函數(shù)以供調(diào)用,比如:當(dāng)用double類型使用函數(shù)模板時(shí),編譯器通過對(duì)實(shí)參類型的推演, 將T確定為double類型,然后產(chǎn)生一份專門處理double類型的代碼,對(duì)于字符類型也是如此。
?實(shí)例化
? ? 用不同類型的參數(shù)使用函數(shù)模板時(shí),稱為函數(shù)模板的實(shí)例化,模板參數(shù)實(shí)例化分為:隱式實(shí)例化 和顯式實(shí)例化。
1. 隱式實(shí)例化:讓編譯器根據(jù)實(shí)參推演模板參數(shù)的實(shí)際類型
template
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);
? ?return 0;
}
注意:在模板中,編譯器一般不會(huì)進(jìn)行類型轉(zhuǎn)換操作,因?yàn)橐坏┺D(zhuǎn)化出問題,編譯器就需要 背黑鍋 ? ?
Add(a1, d1);
此時(shí)有兩種處理方式:
1. 用戶自己來強(qiáng)制轉(zhuǎn)化
2. 使用顯式實(shí)例化
Add(a, (int)d);
2. 顯式實(shí)例化:在函數(shù)名后的<>中指定模板參數(shù)的實(shí)際類型
int main(void)
{
? ?int a = 10;
? ?double b = 20.0;
? ?
? ?// 顯式實(shí)例化
? ?Add
? ?return 0;
}
如果類型不匹配,編譯器會(huì)嘗試進(jìn)行隱式類型轉(zhuǎn)換,如果無法轉(zhuǎn)換成功編譯器將會(huì)報(bào)錯(cuò)。
模版參數(shù)的匹配原則?
1. 一個(gè)非模板函數(shù)可以和一個(gè)同名的函數(shù)模板同時(shí)存在,而且該函數(shù)模板還可以被實(shí)例化為這 個(gè)非模板函數(shù)
// 專門處理int的加法函數(shù)
?int Add(int left, int right)
{
? ? ?return left + right;
}
?
?// 通用加法函數(shù)
?template
?T Add(T left, T right)
{
? ? ?return left + right;
}
?
?void Test()
{
? ? ?Add(1, 2); ? ? ? // 與非模板函數(shù)匹配,編譯器不需要特化
? ? ?Add
}
?2. 對(duì)于非模板函數(shù)和同名函數(shù)模板,如果其他條件都相同,在調(diào)動(dòng)時(shí)會(huì)優(yōu)先調(diào)用非模板函數(shù)而 不會(huì)從該模板產(chǎn)生出一個(gè)實(shí)例,如果模板可以產(chǎn)生一個(gè)具有更好匹配的函數(shù), 那么將選擇模板
// 專門處理int的加法函數(shù)
?int Add(int left, int right)
{
? ? ?return left + right;
}
?
?// 通用加法函數(shù)
?template
?T1 Add(T1 left, T2 right)
{
? ? ?return left + right;
}
?
?void Test()
{
? ? ?Add(1, 2); ? ? // 與非函數(shù)模板類型完全匹配,不需要函數(shù)模板實(shí)例化
? ? ?Add(1, 2.0); ? // 模板函數(shù)可以生成更加匹配的版本,編譯器根據(jù)實(shí)參生成更加匹配的
Add函數(shù)
}
三、類模版
定義格式
templateclass T1, class T2, ..., class Tn>
class 類模板名
{
// 類內(nèi)成員定義
};
#include
using namespace std;
// 類模版
template
class Stack
{
public:
Stack(size_t capacity = 4)
{
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}
void Push(const T& data);
private:
T* _array;
size_t _capacity;
size_t _size;
};
template
void Stack
{
// 擴(kuò)容
_array[_size] = data;
++_size;
}
int main()
{
Stack
Stack
return 0;
}
? ? ?模版不建議聲明和定義分離到兩個(gè)文件.h 和.cpp會(huì)出現(xiàn)鏈接錯(cuò)誤。
實(shí)例化
? ? 類模板實(shí)例化與函數(shù)模板實(shí)例化不同,類模板實(shí)例化需要在類模板名字后跟<>,然后將實(shí)例化的 類型放在<>中即可,類模板名字不是真正的類,而實(shí)例化的結(jié)果才是真正的類。
// Stack是類名,Stack才是類型
Stackint> st1; ? ?// int
Stackdouble> st2; // double
? ? ?本篇關(guān)于模版的一些知識(shí)就到這里了,希望對(duì)各位有幫助,如果有錯(cuò)誤歡迎指出。
?
柚子快報(bào)邀請(qǐng)碼778899分享:C++:模版初階
好文閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。