柚子快報邀請碼778899分享:【C++】模板初階
柚子快報邀請碼778899分享:【C++】模板初階
?個人主頁: 起名字真南 ?個人專欄:【數(shù)據(jù)結(jié)構(gòu)初階】 【C語言】 【C++】
目錄
1 引言2 函數(shù)模板2.1 通過函數(shù)重載的方式實現(xiàn)swap函數(shù)2.2 通用使用函數(shù)模板的方式實現(xiàn)swap函數(shù)2.2.1 函數(shù)模板格式
2.3 函數(shù)模板實現(xiàn)原理2.4 函數(shù)模板的實例化2.4.1 隱式實例化2.4.2 顯示實例化
2.4 函數(shù)模板的特化
3 類模板3.1 類模板的定義格式3.2 類模板的實例化
1 引言
C++ 模板是實現(xiàn)泛型編程的強(qiáng)大工具,允許我們編寫適用于多種數(shù)據(jù)類型的通用代碼。通過模板,我們可以創(chuàng)建函數(shù)和類,而不需要為每種數(shù)據(jù)類型重復(fù)代碼。例如,一個簡單的交換函數(shù)可以通過模板實現(xiàn),以支持 int、double、string 等不同類型。 模板不僅減少了代碼重復(fù),還提升了代碼的靈活性和復(fù)用性。接下來,我們將介紹 C++ 中的函數(shù)模板、類模板和模板特化,帶你了解如何用模板編寫高效、通用的代碼。
#mermaid-svg-Q6vWtZ7sh4HgmiBo {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .error-icon{fill:#552222;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .marker.cross{stroke:#333333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .cluster-label text{fill:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .cluster-label span{color:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .label text,#mermaid-svg-Q6vWtZ7sh4HgmiBo span{fill:#333;color:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .node rect,#mermaid-svg-Q6vWtZ7sh4HgmiBo .node circle,#mermaid-svg-Q6vWtZ7sh4HgmiBo .node ellipse,#mermaid-svg-Q6vWtZ7sh4HgmiBo .node polygon,#mermaid-svg-Q6vWtZ7sh4HgmiBo .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .node .label{text-align:center;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .node.clickable{cursor:pointer;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .arrowheadPath{fill:#333333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .cluster text{fill:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo .cluster span{color:#333;}#mermaid-svg-Q6vWtZ7sh4HgmiBo div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Q6vWtZ7sh4HgmiBo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
模板
函數(shù)模板
類模板
2 函數(shù)模板
函數(shù)模板是 C++ 提供的用于定義通用函數(shù)的一種方式。通過函數(shù)模板,你可以創(chuàng)建一個函數(shù),使它能夠處理不同類型的數(shù)據(jù),而不必為每種類型編寫單獨的函數(shù)。
2.1 通過函數(shù)重載的方式實現(xiàn)swap函數(shù)
#include
using namespace std;
void swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
void swap(double& x, double& y)
{
double tmp = x;
x = y;
y = tmp;
}
void swap(char& x, char& y)
{
char tmp = x;
x = y;
y = tmp;
}
我們通過函數(shù)重載的方式雖然能夠?qū)崿F(xiàn)不同類型數(shù)據(jù)之間的交換但是還存在一些缺點: 1 :需要實現(xiàn)的代碼量比較大,需要為每一種類型都編寫一段代碼 2 :代碼的可擴(kuò)展性比較差,每當(dāng)有新的類型出現(xiàn)都需要手動添加代碼 3: 如果函數(shù)的參數(shù)比較多當(dāng)這些參數(shù)類型可以組合時,可能需要定義大量重載函數(shù)。 4 : 代碼的可維護(hù)性比較差,出現(xiàn)錯誤的時候修改的工程量比較大
2.2 通用使用函數(shù)模板的方式實現(xiàn)swap函數(shù)
2.2.1 函數(shù)模板格式
template
返回值類型 函數(shù)名(參數(shù)列表)
{函數(shù)體}
template
void swap(T& t1, T& t2)
{
T tmp = t1;
t1 = t2;
t2 = tmp;
}
注意模板中的typename是用來定義模板參數(shù)的關(guān)鍵字,可以換成class,(但是切記不能使用struct)
2.3 函數(shù)模板實現(xiàn)原理
在編譯器編譯階段,對于模板函數(shù)的使用,編譯器需要根據(jù)傳入的實參類型來推演生成對應(yīng)類型的函數(shù)用來調(diào)用。比如當(dāng)double類型使用函數(shù)模板時,編譯器通過對實參類型的推演,將T 推演成double類型,然后專門產(chǎn)生一份處理double類型的代碼
2.4 函數(shù)模板的實例化
在 C++ 中,函數(shù)模板的實例化是指在調(diào)用函數(shù)模板時為其指定具體的數(shù)據(jù)類型。編譯器會根據(jù)傳入的參數(shù)類型自動推導(dǎo)出模板參數(shù)類型,或者你也可以顯式地指定類型。
2.4.1 隱式實例化
template
void swap(T& t1, T& t2)
{
T tmp = t1;
t1 = t2;
t2 = tmp;
}
int main()
{
int a = 10;
double b = 20.0;
swap(a, b);
return 0;
}
這里需要注意,如果這樣寫編譯器是無法通過編譯的,因為在函數(shù)模板中兩個參數(shù)是相同的,可是我們在調(diào)用swap函數(shù)的時候傳入的a,b兩個參數(shù)分別是int,double兩種類型,所以我們要知道在進(jìn)行推演的時候是不支持隱式類型轉(zhuǎn)換的 我們有兩個解決方法:
強(qiáng)制類型轉(zhuǎn)換:
int main()
{
int a = 10;
double b = 20.0;
swap(a, (int)b);
return 0;
}
如果我們輸入了這串代碼依舊會報錯這是因為什么呢?(編譯環(huán)境VS2022其他版本可能不會出現(xiàn)這種問題) 出現(xiàn)這個問題的原因也是在發(fā)生在類型推導(dǎo)的過程中的,因為在推導(dǎo)第一個函數(shù)參數(shù)是a的類型是int類型,所以T推演的結(jié)果就是int類型,但是當(dāng)推導(dǎo)第二個類型的時候雖然我們通過強(qiáng)制類型轉(zhuǎn)換(int)將double類型的變量b轉(zhuǎn)換成了int類型但是編譯器還是會按照他的第一個類型進(jìn)行推演,因為推演的過程發(fā)生在類型轉(zhuǎn)換之前,因為推導(dǎo)的過程是在函數(shù)編譯的階段進(jìn)行的
2.4.2 顯示實例化
int main()
{
int a = 10;
double b = 20.0;
swap
return 0;
}
在函數(shù)名后面的<>中指定模板參數(shù)的實際類型,但是如果類型不匹配編譯器依然還是會報錯,報錯的愿意同隱式實例化。
那么我們到底該如何去解決這種問題呢? 第一種方法 : 我們將模板參數(shù)的類型從一個增加為兩個:
template
void swap(T1& t1, T2& t2)
{
T1 tmp = t1;
t1 = t2;
t2 = tmp;
}
第二種解決方法:我們就需要函數(shù)模板的特化來解決這種問題
2.4 函數(shù)模板的特化
所謂函數(shù)模板的特化,就是指我們雖然有了一個函數(shù)模板但是為了一些特殊的函數(shù)類型我們將原代碼重新編寫與之對應(yīng)的類型。比如我們上面的swap函數(shù)只能進(jìn)行相同類型數(shù)據(jù)的轉(zhuǎn)換,但是并不能滿足實際的情況所以我重載了一個新的swap函數(shù),這個新的函數(shù)就叫做特化。
template
void swap(T& t1, T& t2)
{
T tmp = t1;
t1 = t2;
t2 = tmp;
}
void swap(int& x, double& y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 10;
double b = 20.0;
swap(a, b);
return 0;
}
3 類模板
3.1 類模板的定義格式
template
class 類模板名
{
//類內(nèi)成員定義
};
template
class Stack
{
public:
Stack(size_t capacity = 4)
{
_arr = new T[capacity];
_capacity = capacity;
_size = 0;
}
void Push(const T& data);
private:
T* _arr;
size_t _size;
size_t _capacity;
};
template
void Stack
{
_arr[_size] = data;
++_size;
}
int main()
{
Stack
Stack
s1.Push(1);
s2.Push(2.0);
return 0;
}
運(yùn)行結(jié)果:
3.2 類模板的實例化
類模板的實例化與函數(shù)模板的實例化不同,類模板實例化需要在類名的后面加上<>,然后再里面加上類型,如果缺少就會報錯,不會像函數(shù)模板一樣進(jìn)行推導(dǎo)。
//Stack是類名,Stack
Stack
Stack
柚子快報邀請碼778899分享:【C++】模板初階
好文鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。