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