【C++】模板上(泛型編程) —— 函數模板與類模板

文章目錄

  • 一、啥是泛型編程
  • 二、函數模板
    • 2.1、函數模板的概念
    • 2.2、函數模板的格式
    • 2.3、函數模板的原理
    • 2.4、函數模板的實例化
        • 2.4.1、隱式實例化:讓編譯器根據實參推演模板參數的實際類型
        • 2.4.2、顯示實例化:在函數名后的<>中指定模板參數的實際類型
    • 2.5、函數模板的匹配原則
        • 2.5.1、一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化為這個非模板函數
        • 2.5.2、對于非模板函數和同名的函數模板,如果其他條件都相同,在調用時會優先調用非模板函數,而不會從該模板產生出一個實例。如果模板可以產生一個具有更好匹配的函數,那么選擇模板
        • 2.5.3、模板函數不允許自動隱式類型轉換,但普通函數可以進行自動隱式類型轉換
  • 三、類模板
    • 3.1、類模板的定義格式
    • 3.2、類模板的實例化
    • 四、模板的作用域


一、啥是泛型編程

我們在C++中不使用模板(泛型),如何實現一個通用的交換函數呢?

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;
}......
  • 答案也是非常簡單,利用C++的函數重載特性,編寫多個類型的Swap交換函數即可。

但是,這代碼就是咱們程序🐵所說的屎山代碼。因為:

  1. 重載的多個函數僅僅只是類型不同,代碼的復用率比較低只要出現新的類型需要交換,就需要新增對應的重載函數。(QAQ)想到不才都忍不住流淚
  2. 代碼的可維護性比較低,其中一個重載函數出現錯誤可能意味著所有的重載函數都出現了錯誤。

那能否告訴編譯器一個模子,讓編譯器根據不同的類型利用該模子來生成代碼呢?

例如咱們工業生產的時候,是不是只需要生成一個摸具,一壓一和就完成生成產品,不用人工每一個都手打。

在這里插入圖片描述

那么在C++中,我們就隆重推出了泛型編程的概念,這也是C++能在歷朝歷代的語言更替中,依舊呲碴風云的核心之一。

泛型編程:編寫與類型無關的通用代碼,是代碼復用的一種手段。模板是泛型編程的基礎。

在這里插入圖片描述


二、函數模板

2.1、函數模板的概念

函數模板代表了一個函數家族,該函數模板與類型無關,在使用時被參數化,根據實參類型產生函數的特定類型版本。

2.2、函數模板的格式

template <typename T1,class T2,,typename Tn>
返回類型 函數名(參數列表)
{//函數體
}

在這里插入圖片描述

template<typename T>
void Swap(T& x, T& y)
{T tmp = x;x = y;y = tmp;
}

注意typename 是用來定義模板參數關鍵字,也可以用class代替 (切記:不能使用struct代替class),其作用都一樣,只是為了編寫模板參數增多時,代碼可讀性區分自定義類型的模板參數還是基礎類型模板參數。


2.3、函數模板的原理

函數模板是一個藍圖,它本身并不是函數。是編譯器產生特定具體類型函數的模具。所以其實模板就是將本來應該我們做的重復的事情交給了編譯器。

在這里插入圖片描述

在編譯器編譯階段,對于函數模板的使用,編譯器需要根據傳入的實參類型來推演生成對應類型的函數以供調用。比如,當用int類型使用函數模板時,編譯器通過對實參類型的推演,將T確定為int類型,然后產生一份專門處理int類型的代碼,對于double類型等其他也是如此。(所有類型都可以使用泛型編程,包含自定義類型)

2.4、函數模板的實例化

用不同類型的參數使用模板時,稱為模板的實例化。模板實例化分為:隱式實例化顯示實例化


2.4.1、隱式實例化:讓編譯器根據實參推演模板參數的實際類型

在這里插入圖片描述

#include <iostream>
using namespace std;
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}
int main()
{int a = 10, b = 20;int c = Add(a, b); //編譯器根據實參a和b推演出模板參數為int類型return 0;
}
  • 不才在上面代碼中,只聲明了一個泛型變量T
  • 那么在代碼中沒有顯示的指定泛型類型,那么編譯器就根據實參ab推演出模板參數為int類型
  • 即:在編譯后,類型T就會變為Add()函數創建一個int Add(const int& x, const int& y),那就是在2.3、函數模板的原理中不才畫的示例圖,不才再次把這個圖拿下來在這里插入圖片描述

特別注意:使用模板時,程序猿定義了多少個泛型模板變量,那么編譯器就只會自動識別多少個變量。若超出了泛型模板變量定義的個數就報錯

在這里插入圖片描述

#include <iostream>
using namespace std;
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}
int main()
{int a = 10;double dou = 20.2;int c = Add(a, dou); //ERRreturn 0;
}

運行結果如下圖:在這里插入圖片描述

  • 因為在編譯期間,編譯器根據實參推演模板參數的實際類型,根據實參aT推演為int,根據實參douT推演為double,但是模板參數列表中只有一個T,編譯器無法確定此處應該將T確定為int還是double

此時,我們有三種處理方式第一種就是我們在傳參時將dou強制轉換為int類型第二種就是使用下面說到的顯示實例化第三種就是改變函數列表或新增函數使得函數重載


2.4.2、顯示實例化:在函數名后的<>中指定模板參數的實際類型

在這里插入圖片描述

#include <iostream>
using namespace std;
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}
int main()
{int a = 10;double b = 1.1;int c = Add<int>(a, b); //指定模板參數的實際類型為intreturn 0;
}

顯示實例化 一般在類模板中的 類成員的實例化中常見

注意使用顯示實例化時,如果傳入的參數類型與模板參數類型不匹配編譯器會嘗試進行隱式類型轉換,如果無法轉換成功,則編譯器將會報錯


2.5、函數模板的匹配原則

2.5.1、一個非模板函數可以和一個同名的函數模板同時存在,而且該函數模板還可以被實例化為這個非模板函數
#include <iostream>
using namespace std;
//專門用于int類型加法的非模板函數
int Add(const int& x, const int& y)
{return x + y;
}
//通用類型加法的函數模板
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}
int main()
{int a = 10, b = 20;int c = Add(a, b); //調用非模板函數,編譯器不需要實例化int d = Add<int>(a, b); //調用編譯器實例化的Add函數return 0;
}

2.5.2、對于非模板函數和同名的函數模板,如果其他條件都相同,在調用時會優先調用非模板函數,而不會從該模板產生出一個實例。如果模板可以產生一個具有更好匹配的函數,那么選擇模板
#include <iostream>
using namespace std;
//專門用于int類型加法的非模板函數
int Add(const int& x, const int& y)
{return x + y;
}
//通用類型加法的函數模板
template<typename T1, typename T2>
T1 Add(const T1& x, const T2& y)
{return x + y;
}
int main()
{int a = Add(10, 20); //與非模板函數完全匹配,不需要函數模板實例化int b = Add(2.2, 2); //函數模板可以生成更加匹配的版本,編譯器會根據實參生成更加匹配的Add函數return 0;
}

2.5.3、模板函數不允許自動隱式類型轉換,但普通函數可以進行自動隱式類型轉換

普通函數可以進行自動隱式類型轉換

在這里插入圖片描述

int Add(const int& x, const int& y)
{return x + y;
}int main()
{int a = Add(10, 20);int b = Add(2.2, 2); int t = Add(5.5, 5.5); printf("a :> %d\n", a);printf("b :> %d\n", b);printf("t :> %d\n", t);return 0;
}

運行結果:
在這里插入圖片描述

模板函數不允許自動隱式類型轉換

在這里插入圖片描述

#include <iostream>
using namespace std;
template<typename T>
T Add(const T& x, const T& y)
{return x + y;
}
int main()
{int a = 10;double dou = 20.2;int c = Add(a, dou); //ERRreturn 0;
}

運行結果如下圖:在這里插入圖片描述


三、類模板

3.1、類模板的定義格式

template<class T1, class T2,, class Tn>
class 類模板名
{//類內成員聲明
};

在這里插入圖片描述

template<class T>
class Score
{
public:Score(T math, T chinese, T english) :_Math(math), _Chinese(chinese), _English(english) {;}void Print(){cout << "數學:" << _Math << endl;cout << "語文:" << _Chinese << endl;cout << "英語:" << _English << endl;}
private:T _Math;T _Chinese;T _English;
};

注意類模板中的成員函數/屬性若是放在類外定義時,需要加模板參數列表。(一般使用在靜態方法中)

在這里插入圖片描述

template<class T>
class Score
{
public:Score(T chinese, T english) :_Chinese(chinese), _English(english) {;}void Print();//為舉例而寫private:static int _Math;T _Chinese;T _English;
};
template <class T>
int Score<T>::_Math = 10;template <class T>
void Score<T>::Print()
{cout << "數學:" << _Math << endl;cout << "語文:" << _Chinese << endl;cout << "英語:" << _English << endl;
}

3.2、類模板的實例化

類模板實例化需要在類模板名字后面<>,然后將實例化的類型放在<>即可。

在這里插入圖片描述

template<class T>
class Score
{
public:Score(T chinese, T english) :_Chinese(chinese), _English(english) {;}void Print();private:static int _Math;T _Chinese;T _English;
};
template <class T>
int Score<T>::_Math = 10;template <class T>
void Score<T>::Print()
{cout << "數學:" << _Math << endl;cout << "語文:" << _Chinese << endl;cout << "英語:" << _English << endl;
}int main() {Score<int> t1( 100, 60);Score<double> t2( 90.5, 2.5);t1.Print();
}

注意Score不是真正的Score<int>Score<double>才是真正的

類模板名字不是真正的類,而實例化的結果才是真正的類。


四、模板的作用域

不論是類模板、函數模板還是類外定義的內容中,template其作用域只會最用在下面最近一行中

在這里插入圖片描述

template<class T>
class Score
{
public:Score(T chinese, T english) :_Chinese(chinese), _English(english) {;}void Print();//為舉例而寫private:static int _Math;T _Chinese;T _English;
};template <class T>
int Score<T>::_Math = 10;
void Score<T>::Print() //err
{cout << "數學:" << _Math << endl;cout << "語文:" << _Chinese << endl;cout << "英語:" << _English << endl;
}
  • 在類外第一個定義的template <class T>只作用在int Score<T>::_Math = 10;中,之后就消亡
  • 所以在void Score<T>::Print(){...}中,T不再是一個類模板,而是一個未定義的標識符。如下圖:在這里插入圖片描述

那為啥我們在類中或函數中還是可以使用模板參數呢?

  • 那是因為在{}中內容都是屬于該類/函數的內容

以上就是本章所有內容。若有勘誤請私信不才。萬分感激💖💖 如果對大家有用的話,就請多多為我點贊收藏吧,您的每一個點贊都是不才最大的鼓勵~~~💖💖
請添加圖片描述

ps:表情包來自網絡,侵刪🌹

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81623.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81623.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81623.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

語音識別-2

目錄 1.藍牙優化 1.打開sco 2.外放時的藍牙的不同版本適配 2.微軟文本轉語音優化 1.異步文本轉語音 2.語音的個性化 上一篇關于語音識別, 雖然能用,但在系統適配,機器適配方面,速度,性能等還是有優化的地方.所以這篇是關于這些的. 1.藍牙優化 A2DP:是一種單向的高品質音…

【springcloud學習(dalston.sr1)】服務消費者通過restTemplate來訪問服務提供者(含源代碼)(五)

該系列項目整體介紹及源代碼請參照前面寫的一篇文章??????【springcloud學習(dalston.sr1)】項目整體介紹&#xff08;含源代碼&#xff09;&#xff08;一&#xff09; springcloud學習&#xff08;dalston.sr1&#xff09;系統文章匯總如下&#xff1a; 【springcloud…

小白學編程之——數據庫如何性能優化

小白學編程之——數據庫性能優化指南 數據庫如同一個大型倉庫&#xff0c;性能優化就是幫助倉庫管理員&#xff08;數據庫&#xff09;更高效地存取貨物&#xff08;數據&#xff09;。本文將以通俗易懂的方式&#xff0c;帶你避開常見誤區&#xff0c;讓數據庫運行得更快更穩…

SQLMesh信號機制詳解:如何精準控制模型評估時機

SQLMesh的信號機制為數據工程師提供了更精細的模型評估控制能力。本文深入解析信號機制的工作原理&#xff0c;通過簡單和高級示例展示如何自定義信號&#xff0c;并提供實用的使用技巧和測試方法&#xff0c;幫助讀者優化數據管道的調度效率。 一、為什么需要信號機制&#xf…

FreeSWITCH 簡單圖形化界面43 - 使用百度的unimrcp搞個智能話務臺,用的在線的ASR和TTS

FreeSWITCH 簡單圖形化界面43 - 使用百度的unimrcp搞個智能話務臺 0、一個fs的web配置界面預覽1、安裝unimrcp模塊2、安裝完成后&#xff0c;配置FreeSWITCH。2.1 有界面的配置2.1.1 mod_unimrcp模塊配置2.1.2 mod_unimrcp客戶端配置 2.2 無界面的配置 3、呼叫規則4、編寫流程4…

【架構】RUP統一軟件過程:企業級軟件開發的全面指南

一、RUP概述 RUP(Rational Unified Process&#xff0c;統一軟件過程)是由Rational Software公司(后被IBM收購)開發的一種迭代式軟件開發過程框架。它結合了傳統瀑布模型的系統性和敏捷方法的靈活性&#xff0c;為中大型軟件項目提供了全面的開發方法論。 RUP不僅僅是一種過程…

DeepSeek賦能電商,智能客服機器人破解大型活動人力困境

1. DeepSeek 與電商客服結合的背景 1.1 電商行業客服需求特點 電商行業具有獨特的客服需求特點&#xff0c;這些特點決定了智能客服機器人在該行業的必要性和重要性。 高并發性&#xff1a;電商平臺的用戶數量龐大&#xff0c;尤其是在促銷活動期間&#xff0c;用戶咨詢量會…

面向具身智能的視覺-語言-動作模型(VLA)綜述

具身智能被廣泛認為是通用人工智能&#xff08;AGI&#xff09;的關鍵要素&#xff0c;因為它涉及控制具身智能體在物理世界中執行任務。在大語言模型和視覺語言模型成功的基礎上&#xff0c;一種新的多模態模型——視覺語言動作模型&#xff08;VLA&#xff09;已經出現&#…

后端框架(1):Mybatis

什么是框架&#xff1f; 蓋高樓&#xff0c;框架結構。 框架結構就是高樓的主體&#xff0c;基礎功能。 把很多基礎功能已經實現了(封裝了)。 在基礎語言之上&#xff0c;對各種基礎功能進行封裝&#xff0c;方便開發者&#xff0c;提高開發效率。 mybatis&#xff1a;對jd…

ubuntu20.04系統搭建k8s1.28集群-docker作為容器運行時

ubuntu系統搭建 ubuntu-22.04.5-desktop-amd64.iso映像文件--->實際卻是20.4focal版本。 【安裝過程沒有特別指出的默認回車下一步】 【用戶和密碼設置】 【網絡連接】 【在vmware上安裝的話&#xff0c;網絡配置如下】【在vm里配置選擇nat或者橋接即可】 【國內源配置】&…

軟件I2C

軟件I2C 注意&#xff1a; SDA&#xff08;串行數據線&#xff09;和SCL&#xff08;串行時鐘線&#xff09;都是雙向I/O線&#xff0c;接口電路為開漏輸出。需通過上拉電阻接電源VCC。 軟件I2C說明 說明&#xff0c;有的單片機沒有硬件I2C的功能&#xff0c;或者因為電路設計…

C++性能測試工具——Vtune的使用

一、Intel Vtune的安裝 在前面初步認識了一下幾個性能的測試工具&#xff0c;本篇重點介紹一下Intel VTune Profiler&#xff0c;VTune是一個強大的性能分析工具&#xff0c;它屬于Intel oneAPI工具包中工具的一種。VTune的安裝只介紹在Linux平臺下的場景&#xff08;Windows安…

互聯網大廠Java求職面試:優惠券服務架構設計與AI增強實踐-6

互聯網大廠Java求職面試&#xff1a;優惠券服務架構設計與AI增強實踐-6 場景設定&#xff1a;技術總監張總坐在會議室里&#xff0c;鄭薪苦帶著自信的微笑走了進來。今天他們要圍繞優惠券服務的架構設計及如何結合AI進行增強展開討論。 第一輪面試&#xff1a;基礎架構設計 …

nginx模塊使用、過濾器模塊以及handler模塊

一、如何使用nginx的模塊 1.ngx_code.c: #include "ngx_config.h" #include "ngx_conf_file.h" #include "nginx.h" #include "ngx_core.h" #include "ngx_string.h" #include "ngx_palloc.h" #include "n…

【Odoo】Pycharm導入運行Odoo15

【Odoo】Pycharm導入運行Odoo15 前置準備1. Odoo-15項目下載解壓2. PsrtgreSQL數據庫 項目導入運行1. 項目導入2. 設置項目內虛擬環境3. 下載項目中依賴4. 修改配置文件odoo.conf 運行Pycharm快捷運行 前置準備 1. Odoo-15項目下載解壓 將下載好的項目解壓到開發目錄下 2. …

網絡安全-等級保護(等保) 2-5 GB/T 25070—2019《信息安全技術 網絡安全等級保護安全設計技術要求》-2019-05-10發布【現行】

################################################################################ GB/T 22239-2019 《信息安全技術 網絡安全等級保護基礎要求》包含安全物理環境、安全通信網絡、安全區域邊界、安全計算環境、安全管理中心、安全管理制度、安全管理機構、安全管理人員、安…

【SpringBoot】??整合飛書群機器人發送消息

&#x1f4a5;&#x1f4a5;????歡迎閱讀本文章????&#x1f4a5;&#x1f4a5; &#x1f3c6;本篇文章閱讀大約耗時3分鐘。 ??motto&#xff1a;不積跬步、無以千里 &#x1f4cb;&#x1f4cb;&#x1f4cb;本文目錄如下&#xff1a;&#x1f381;&#x1f381;&am…

我的多條件查詢

背景&#xff1a;2個表&#xff0c;是一對多的關系&#xff0c;一個實時視頻幀可以出現多個檢測結果 要求&#xff0c;可以根據&#xff0c;ids&#xff0c;起始時間&#xff0c;識別出的鳥的種類&#xff0c;來進行刪除。 出現的問題&#xff0c; 一致性沒有實現&#xff1a…

關于網站提交搜索引擎

發布于Eucalyptus-blog 一、前言 將網站提交給搜索引擎是為了讓搜索引擎更早地了解、索引和顯示您的網站內容。以下是一些提交網站給搜索引擎的理由&#xff1a; 提高可見性&#xff1a;通過將您的網站提交給搜索引擎&#xff0c;可以提高您的網站在搜索結果中出現的機會。當用…

【Oracle專欄】擴容導致數據文件 dbf 丟失,實操

Oracle相關文檔,希望互相學習,共同進步 風123456789~-CSDN博客 1.背景 同事檢查擴容情況,發現客戶擴容后數據盤后,盤中原有文件丟失,再檢查發現數據庫沒有啟動。通過檢查發現數據盤中丟失的是oracle的 dbf 表空間文件。數據庫無法啟動。 檢查情況:1)沒有rman備份 …