網(wǎng)站頁(yè)面怎么做識(shí)別二維碼谷歌引擎搜索入口
【C++】模板初級(jí)
- 泛型編程
- 函數(shù)模板
- 函數(shù)模板的概念
- 函數(shù)模板格式
- 函數(shù)模板的原理
- 函數(shù)模板的實(shí)例化
- 模板參數(shù)的匹配原則
- 類模板
- 類模板格式
- 類模板的實(shí)例化
泛型編程
當(dāng)我們之前了解過(guò)函數(shù)重載后可以知道,一個(gè)程序可以出現(xiàn)同名函數(shù),但參數(shù)類型不同。
//整型
void Swap(int& x, int& y)
{int tmp = x;x = y;y = tmp;
}//浮點(diǎn)型
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;
}int main()
{int a = 1, b = 2;Swap(a, b);double c = 3, d = 4;Swap(c, d);char e = 'a', f = 'b';Swap(e, f);return 0;
}
大家可以發(fā)現(xiàn),使用函數(shù)重載雖然可以實(shí)現(xiàn),但不足之處也很明顯:
1.重載的函數(shù)僅僅時(shí)類型不同,代碼的復(fù)用率比較低,只要有新類型出現(xiàn)時(shí),就需要用戶自己增加對(duì)應(yīng)的函數(shù)
2.代碼的可維護(hù)性比較低,一個(gè)出錯(cuò)可能所有的重載都出錯(cuò)。
那么在C++中就存在這樣一種方式,類似于存在一種模具,通過(guò)給這個(gè)模具填充不同的材料(類型),來(lái)獲得不同材料的鑄件(即生成具體類型的代碼)。
泛型編程:編寫(xiě)與類型無(wú)關(guān)的通用代碼,是代碼復(fù)用的一種手段。模板是泛型編程的基礎(chǔ)。
函數(shù)模板
函數(shù)模板的概念
函數(shù)模板代表了一個(gè)函數(shù)家族,該函數(shù)模板與類型無(wú)關(guān),在使用時(shí)被參數(shù)化,根據(jù)實(shí)參類型產(chǎn)生函數(shù)特定類型模板
函數(shù)模板格式
template<typename T>
void Swap(T& x, T& y)
{T tmp = x;x = y;y = tmp;
}
int main()
{int a = 1, b = 2;Swap(a, b);double c = 3, d = 4;Swap(c, d);char e = 'a', f = 'b';Swap(e, f);return 0;
}
觀察上面代碼,格式為:
template<<typename T1,typename T2,…,typename Tn>>
返回值類型 函數(shù)名(參數(shù)列表){ }
- 注意
1.這倆部分是相對(duì)應(yīng)的,存在一個(gè)函數(shù),就需要在函數(shù)上面增加一段template的聲明
2.typename是用來(lái)定義模板參數(shù)關(guān)鍵字,也可以使用class(切記:不能使用struct代替class)
函數(shù)模板的原理
函數(shù)模板是一個(gè)藍(lán)圖,它本身并不是函數(shù),是編譯器用使用方式產(chǎn)生特定具體類型函數(shù)的模具。所以其實(shí)模板就是將本來(lái)應(yīng)該我們做的重復(fù)的事情交給編譯器。
通過(guò)反匯編的方式觀察下面這段代碼:
在編譯器編譯階段,對(duì)于模板函數(shù)的使用,編譯器需要根據(jù)傳入的實(shí)參類型來(lái)推演生成對(duì)應(yīng)類型的函數(shù)以供調(diào)用。
例如:當(dāng)用double類型使用函數(shù)模板時(shí),編譯器通過(guò)對(duì)實(shí)參類型的推演,將T確定為double類型,然后產(chǎn)生一份專門(mén)處理double類型的代碼,對(duì)于字符類型、整型類型也是如此。
函數(shù)模板的實(shí)例化
用不同類型的參數(shù)使用函數(shù)模板,稱為函數(shù)模板的實(shí)例化。
模板參數(shù)實(shí)例化分為:隱式實(shí)例化和顯示實(shí)例化。
- 隱式實(shí)例化:即讓編譯器根據(jù)實(shí)參推演模板參數(shù)的實(shí)際類型
當(dāng)函數(shù)傳參時(shí),存在不同的倆個(gè)類型時(shí),可以使用隱式實(shí)例化。
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}int main(void)
{int a = 1;double b = 1.2;Add(a, (int)b);Add((double)a, b);return 0;
}
- 顯式實(shí)例化:在函數(shù)名后的<>中指定模板參數(shù)的實(shí)際類型。
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}int main(void)
{int a = 1;double b = 1.2;Add<int>(a, b);Add<double>(a, b);return 0;
}
程序運(yùn)行時(shí)如果類型不匹配,編譯器會(huì)嘗試進(jìn)行隱式類型轉(zhuǎn)換,如果無(wú)法轉(zhuǎn)換成功編譯器將會(huì)報(bào)錯(cuò)。
模板參數(shù)的匹配原則
- 一個(gè)非模板函數(shù)可以和一個(gè)同名函數(shù)模板同時(shí)存在,而且該函數(shù)模板還可以被實(shí)例化為這個(gè)非模板函數(shù)。
- 對(duì)于非模板函數(shù)和同名函數(shù)模板,如果其他條件都相同,在調(diào)用時(shí)會(huì)優(yōu)先調(diào)用非模板函數(shù)而不會(huì)從該模板產(chǎn)生一個(gè)實(shí)例。如果模板可以產(chǎn)生一個(gè)具有更好匹配的函數(shù),那么將選擇模板
- 模板函數(shù)不允許自動(dòng)類型轉(zhuǎn)換,但普通函數(shù)可以進(jìn)行自動(dòng)類型轉(zhuǎn)換。
類模板
類模板格式
tmplate<class T1, class T2, ... ,class Tn>
class name
{
//類內(nèi)成員定義
};
以數(shù)據(jù)結(jié)構(gòu)中的棧為例:
template<class T>
class Stack
{//...
private:T& _arr;int _size;int _capacity;
};
當(dāng)我們需要在順序表中創(chuàng)建不同的類型時(shí),可以使用類模板。
類模板的實(shí)例化
類模板實(shí)例化與函數(shù)模板實(shí)例化不同,類模板實(shí)例化需要在類模板名字后面跟<>,然后將實(shí)例化的類型放在<>中即可,類模板名字不是真正的類,而實(shí)例化的結(jié)果才是真正的類。
template<class T>
class Stack
{//聲明Stack(int capacity = 4);
private:T& _arr;size_t _size;size_t _capacity;
};
//定義
template<class T>
Stack<T>::Stack(int capacity):_capacity(capacity),_size(0)
{_arr = new T[capacity];
}
【注意】對(duì)于普通類而言,類名和類是一樣的;而對(duì)于類模板而言,類名與類型不同。以stack為例子:stack< t >是類型,stack是類名。