日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++ 泛型编程(一):模板基础:函数模板、类模板、模板推演成函数的机制、模板实例化、模板匹配规则

發(fā)布時(shí)間:2023/12/13 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 泛型编程(一):模板基础:函数模板、类模板、模板推演成函数的机制、模板实例化、模板匹配规则 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 泛型編程
  • 函數(shù)模板
    • 函數(shù)模板實(shí)例化
      • 隱式實(shí)例化
      • 顯式實(shí)例化
    • 函數(shù)模板的匹配規(guī)則
  • 類(lèi)模板
    • 類(lèi)模板的實(shí)例化


泛型編程

泛型編程旨在削減重復(fù)工作,如:

  • 將一個(gè)函數(shù)多次重載不如將他寫(xiě)成泛型。
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; }

就比如非常常用的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ě)成泛型。
class Stack {private:int capacity;int size;int* arr; };

如果我們實(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ī)則

  • 一個(gè)非模板函數(shù)可以和一個(gè)同名的函數(shù)模板同時(shí)存在,而且該函數(shù)模板還可以被實(shí)例化為這個(gè)非模板函數(shù)。這時(shí)如果使用隱式實(shí)例化,則會(huì)調(diào)用非模板函數(shù);如果使用顯式實(shí)例化,則調(diào)用模板函數(shù)
  • //非模板函數(shù) int Add(int left, int right) {return left + right; }template<class T> T Add(T left, T right) {return left + right; }int main() {Add(1, 2); // 調(diào)用非模板函數(shù)Add<int>(1, 2); // 調(diào)用模板函數(shù) }
  • 對(duì)于非模板函數(shù)和同名函數(shù)模板,如果其他條件都相同,在調(diào)動(dòng)時(shí)會(huì)優(yōu)先調(diào)用非模板函數(shù)而不會(huì)從該模板產(chǎn)生出一個(gè)實(shí)例。如果模板可以產(chǎn)生一個(gè)具有更好匹配的函數(shù), 那么將選擇模板函數(shù)
  • // 專(zhuān)門(mén)處理int的加法函數(shù) int Add(int left, int right) {return left + right; }// 通用加法函數(shù) template<class T1, class T2> T1 Add(T1 left, T2 right) {return left + right; }void Test() {Add(1, 2); // 與非函數(shù)模板類(lèi)型完全匹配,不需要函數(shù)模板實(shí)例化Add(1, 2.0); // 模板函數(shù)可以生成更加匹配的版本,編譯器根據(jù)實(shí)參生成更加匹配的Add函數(shù) }
  • 模板函數(shù)不允許自動(dòng)類(lèi)型轉(zhuǎn)換,但普通函數(shù)可以進(jìn)行自動(dòng)類(lèi)型轉(zhuǎn)換。

  • 類(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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。