C++ 泛型编程(一):模板基础:函数模板、类模板、模板推演成函数的机制、模板实例化、模板匹配规则
文章目錄
- 泛型編程
- 函數(shù)模板
- 函數(shù)模板實(shí)例化
- 隱式實(shí)例化
- 顯式實(shí)例化
- 函數(shù)模板的匹配規(guī)則
- 類(lèi)模板
- 類(lèi)模板的實(shí)例化
泛型編程
泛型編程旨在削減重復(fù)工作,如:
- 將一個(gè)函數(shù)多次重載不如將他寫(xiě)成泛型。
就比如非常常用的swap函數(shù),雖然c++支持重載,但是如果對(duì)于這種函數(shù)我們每一個(gè)都要自己去實(shí)現(xiàn),是一件很麻煩并且多余的工作,因?yàn)槲覀儗⒅貜?fù)邏輯的東西多次實(shí)現(xiàn)。
- 比如我們想向一個(gè)封裝好的類(lèi)添加新的數(shù)據(jù)成員,重新寫(xiě)一個(gè)不如一開(kāi)始就寫(xiě)成泛型。
如果我們實(shí)現(xiàn)了一個(gè)棧,如果他此時(shí)要存儲(chǔ)其他的數(shù)據(jù)類(lèi)型,那我們就必須還要重新修改一個(gè),這無(wú)疑是繁瑣的。
所以,C++ 基于重載這一項(xiàng)機(jī)制,實(shí)現(xiàn)了模板編程,模板作為類(lèi)或者函數(shù)的藍(lán)圖,可以針對(duì)不同類(lèi)型,來(lái)實(shí)現(xiàn)對(duì)應(yīng)操作。
函數(shù)模板
函數(shù)模板與類(lèi)型無(wú)關(guān),被調(diào)用時(shí)根據(jù)實(shí)參類(lèi)型產(chǎn)生函數(shù)的對(duì)應(yīng)類(lèi)型版本。
template<typename T1, typename T2,......,typename Tn> //typename即類(lèi)型名,也可以用class替代,這里的class指的是類(lèi)型,不能用struct替換編寫(xiě)函數(shù)模板時(shí),只需要在對(duì)應(yīng)的函數(shù)前面加上上面的語(yǔ)句即可,然后將所有需要替換類(lèi)型的參數(shù)改為上面的 T1、T2 即可
template<class T> void Swap(T& left, T& right) {T temp = left;left = right;right = temp; }int main() {int i = 3, j = 4;double a = 3.4, b = 5.6;char x = 'x', y = 'y';Swap(i, j);Swap(a, b);Swap(x, y);cout << i << ' ' << j << endl;cout << a << ' ' << b << endl;cout << x << ' ' << y << endl; }當(dāng)我們調(diào)用這個(gè)模板函數(shù)的時(shí)候,是生成一個(gè)函數(shù)重載并調(diào)用三次呢?還是生成三個(gè)返回值不同的函數(shù)各調(diào)用一次呢?
通過(guò)地址信息可以看到,它調(diào)用的是三個(gè)不同的函數(shù)。
因此,模板函數(shù)本身并不是一個(gè)函數(shù),而是一個(gè)藍(lán)圖,通過(guò)識(shí)別我們傳入的參數(shù),然后在底層生成一個(gè)該類(lèi)型的模板函數(shù),并調(diào)用該函數(shù)。
并且這個(gè)階段是在預(yù)處理的時(shí)候就進(jìn)行了,因?yàn)槿绻窃诰幾g階段才進(jìn)行函數(shù)的生成,那肯定是無(wú)法通過(guò)語(yǔ)法的檢查的,所以這一階段只能在預(yù)處理進(jìn)行。
函數(shù)模板實(shí)例化
函數(shù)模板只在第一次使用的時(shí)候才會(huì)實(shí)例化出來(lái),它的實(shí)例化有兩種方法,一種是顯式實(shí)例化,一種是隱式實(shí)例化。
隱式實(shí)例化
template<class T> T Add(const T& left, const T& right) {return left + right; }int main() {int i = 3, j = 4;double a = 3.4, b = 5.6;Add(i, j);Add(a, b);/*Add(i, a);這時(shí)編譯器就會(huì)報(bào)錯(cuò),因?yàn)樾枰ㄟ^(guò)參數(shù)推演出對(duì)應(yīng)類(lèi)型,但是此時(shí)就無(wú)法推演出到底是將 T 推演成 double 還是將 T 推演成 int*/// 此時(shí)有兩種處理方式:1. 用戶(hù)自己來(lái)強(qiáng)制轉(zhuǎn)化 2. 使用顯式實(shí)例化Add(i, (int)a); // 強(qiáng)制轉(zhuǎn)化,將 T 推演成 intreturn 0; }顯式實(shí)例化
int main() {int i = 3;double x = 3.4;// 顯式實(shí)例化Add<int>(i, x);return 0; }用尖括號(hào)來(lái)顯式的聲明,STL 中的容器等就是采用這種顯式的實(shí)例化來(lái)明確參數(shù)的類(lèi)型。
函數(shù)模板的匹配規(guī)則
類(lèi)模板
類(lèi)模板的用法和函數(shù)模板其實(shí)一樣
template<class T> class Stack {private:int capacity;int size;T* arr; };這里的 Stack 不是一個(gè)具體的類(lèi),他是類(lèi)模板,也就是一個(gè)藍(lán)圖,通過(guò)這個(gè)模板來(lái)識(shí)別參數(shù)的類(lèi)型并生成對(duì)應(yīng)的模板類(lèi)。
所以可以理解為類(lèi)模板是一個(gè)類(lèi)家族,模板類(lèi)是通過(guò)類(lèi)模板實(shí)例化的具體類(lèi)。
如果類(lèi)中的成員函數(shù)需要在類(lèi)外定義的話(huà),需要每一個(gè)定義前都要聲明一次類(lèi)模板的參數(shù)列表。
template<class T> class Stack { public:void push();void pop(); private:int capacity;int size;T* arr; };template<class T> void Stack<T>::push() {}template<class T> void Stack<T>::pop() {}還有一個(gè)需要注意的地方就是,類(lèi)模板的所有成員函數(shù)都是模板函數(shù)。
類(lèi)模板的實(shí)例化
類(lèi)模板只能夠通過(guò)顯式實(shí)例化
如 STL 中的幾個(gè)容器都是通過(guò)類(lèi)模板實(shí)現(xiàn)的:
stack<int> s1;stack<double> s2;stack<int> 并不是類(lèi)名,而是顯式實(shí)例化指定的類(lèi)型,stack 才是類(lèi)名。
總結(jié)
以上是生活随笔為你收集整理的C++ 泛型编程(一):模板基础:函数模板、类模板、模板推演成函数的机制、模板实例化、模板匹配规则的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: sql like N'%%
- 下一篇: s3c2440移植MQTT