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