【C++】模板template

??? ???🔥🔥 歡迎來到小林的博客!!
??????🛰?博客主頁:??林 子
??????🛰?博客專欄:?? C++
??????🛰?社區 :?? 進步學堂
??????🛰?歡迎關注:👍點贊🙌收藏??留言

目錄

認識模板

模板是C++中泛型編程的基礎,一個模板就是一個創建類或者函數的藍圖或者說是公式。

當使用一個vector這樣的泛型類型時,或者find這樣的泛型函數時,我們提供足夠的信息,將藍圖轉化成類或者函數。這種轉化發生在編譯時。

function template函數模板

比如我們想寫一個swap函數來交換兩個數的值,在C++中我們可以用函數重載來重載多個函數來實現對不同類型的交換。比如我們要交換int 和 double類型,那么僅僅重載一個 swap(int& x ,int& y)是不夠的。還需要重載一個swap(double& x,double& y) 函數。 但如果我還想交換其他的類型,也要寫出其他類型對應的函數重載。這樣就顯得十分麻煩。所以這時候我們就可以function template(函數模板) 來減少我們需要寫的代碼。

template<class T> //定義函數模板
void Swap(T& x, T& y) //T是模板參數,也就是你傳入的參數
{T tmp = x;x = y; y = tmp;
}
int main()
{int i1 = 5, i2 = 10;double d1 = 5.5, d2 = 10.5;string str1 = "hello", str2 = "world";cout << "交換前:" << endl;cout << "i1 : " << i1 << " , i2 :" << i2 << endl;cout << "d1 : " << d1 << " , d2 :" << d2 << endl;cout << "str1 : " << str1 << " , str2 :" << str2 << endl;Swap(i1, i2);Swap(d1, d2);Swap(str1, str2);cout << "交換后:" << endl;cout << "i1 : " << i1 << " , i2 :" << i2 << endl;cout << "d1 : " << d1 << " , d2 :" << d2 << endl;cout << "str1 : " << str1 << " , str2 :" << str2 << endl;return 0;
}

代碼運行結果:

在這里插入圖片描述

我們寫了一份代碼,就可以交換所有類型,而不用頻繁的去自己寫函數重載。

class類模板

類模板是用來生成類的藍圖,與函數模板不同的是,編譯器不能為類模板推斷模板參數類型。為了使用類模板,我們必須在類名后面加<>中提供額外信息。

template <class T>
class Node
{
public:void fun(){cout << "T* : " << typeid(next).name() << endl;cout << "T : " << typeid(val).name() << endl;}
private:T* next;T val;
};int main()
{Node<int> ni;ni.fun();cout << endl;Node<double> nd;nd.fun();cout << endl;Node<char> nc;nc.fun();return 0;
}

運行結果:

在這里插入圖片描述

此時我們就可以發現,你<>中傳什么類型進去,那么你類中的T就是什么類型。這就大大的方便了我們的編碼,如果沒有模板,那么每個類型都要安插一個這樣的類出來,是非常麻煩的。

模板特化

如果你想對不同的模板參數,做不同的處理,那么此時你可以用模板指定類型。比如你有一個正常的模板,但是當模板參數為double時想做一下特殊處理,那么我們可以再定義一個類型模板的類。這樣再生成模板時會優先生成最匹配的那一項

//普通模板
template<class T>
class A
{
public:A(){cout << "T()" << endl; }
};//特化
template<>
class A<double>
{
public:A(){cout << "double()" << endl;}
};int main()
{A<int> ai;A<char> ac;A<double>ad;return 0;
}

我們來看看它們會調用哪些構造函數。

在這里插入圖片描述

我們發現,當在其他模板參數類型時會調用T(),但是當模板參數為double時,調用的是double()。 這也就意味著當模板參數為double時,那么會優先選擇最匹配的。這種行為被稱為特化。

半特化(偏特化)

當你要傳入的模板參數,一半需要自動推導,一半又需要自己定義時,可以使用半特化。

template<class T1,class T2>
class A
{
public:A(){cout << "A<T1,T2>" << endl; }
};template<class T1>
class A<T1,char>
{
public:A(){cout << "A<T1,char>" << endl;}
};int main()
{A<int,int> a1;A<double,char> a2;A<char,char>a3;return 0;
}

運行結果:

在這里插入圖片描述

我們發現,只要一個模板參數對應,那么就會優先選擇對應的那個。

模板原理

模板的原理其實就是根據你所傳的模板參數,又給你自動生成了一個類。而這個過程在編譯時發生。就比如如下這個代碼。

template<class T1,class T2>
class A
{
public:T1 a;T2 b;
};int main()
{A<int,int> a1;A<double,char> a2;A<char,char>a3;return 0;
}

它在編譯后實際上是這樣的

class A
{
public:int a;int b;
};class A
{
public:double a;char b;
};class A
{
public:char a;char b;
};

會生成三個A類。分別對應的模板參數

A<int,int> a1;
A<double,char> a2;
A<char,char>a3;

當然,我們在編碼的時候是無法用相同的類名的。但在編譯時,會有類似于函數重載的機制(個人猜測)生成出多個類。

所以,函數模板的本質就是方便你編碼。等編譯時再為你自動生成你當初傳入的模板參數時對應的類。也就是說,雖然表面上你寫的代碼減少了,但本質上需要的代碼并沒有減少。只是在編譯時為你自動生成了。

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

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

相關文章

Django之定時任務--apscheduler

Django--定時任務apscheduler的使用 apscheduler定時任務的使用1、安裝包2、配置settings.py3、在manage.py的文件同級目錄下創建文件scheduler.py4、在項目的urls.py中調用這個定時計劃5、然后啟動項目 python manage.py runserver,在admin中查看就能看到你的定時任務及執行的…

機器學習算法之-邏輯回歸(1)

什么是回歸 回歸樹&#xff0c;隨機森林的回歸&#xff0c;無一例外他們都是區別于分類算法們&#xff0c;用來處理和預測連續型標簽的算法。然而邏輯回歸&#xff0c;是一種名為“回歸”的線性分類器&#xff0c;其本質是由線性回歸變化而來的&#xff0c;一種廣泛使用于分類問…

Vue 引入 Element-UI 組件庫

Element-UI 官網地址&#xff1a;https://element.eleme.cn/#/zh-CN 完整引入&#xff1a;會將全部組件打包到項目中&#xff0c;導致項目過大&#xff0c;首次加載時間過長。 下載 Element-UI 一、打開項目&#xff0c;安裝 Element-UI 組件庫。 使用命令&#xff1a; npm …

ArcGIS Maps SDK for JavaScript系列之二:認識Map和MapView

目錄 Map創建一個 Map 對象的示例代碼&#xff1a;Map的常用屬性Map的常用方法 MapViewMapView的常用屬性MapView的常用方法 在 ArcGIS Maps SDK for JavaScript 中&#xff0c;Map 和 MapView 是兩個重要的概念&#xff0c;用于創建和展示地圖應用程序。 Map Map 表示一個地圖…

【Rust】Rust學習 第十三章Rust 中的函數式語言功能:迭代器與閉包

Rust 的設計靈感來源于很多現存的語言和技術。其中一個顯著的影響就是 函數式編程&#xff08;functional programming&#xff09;。函數式編程風格通常包含將函數作為參數值或其他函數的返回值、將函數賦值給變量以供之后執行等等。 更具體的&#xff0c;我們將要涉及&#…

bert,transformer架構圖及面試題

Transformer詳解 - mathor atten之后經過一個全連接層殘差層歸一化 class BertSelfOutput(nn.Module):def __init__(self, config):super().__init__()self.dense nn.Linear(config.hidden_size, config.hidden_size)self.LayerNorm nn.LayerNorm(config.hidden_size, epscon…

redis 發布和訂閱

目錄 一、簡介 二、常用命令 三、示例 一、簡介 Redis 發布訂閱 (pub/sub) 是一種消息通信模式&#xff1a;發送者 (pub) 發送消息&#xff0c;訂閱者 (sub) 接收消息。Redis 客戶端可以訂閱任意數量的頻道。下圖展示了頻道 channel1 &#xff0c;以及訂閱這個頻道的三個客戶…

前端對文件轉換處理的一些常用方法

文章目錄 0&#xff0c;前言1&#xff0c;將圖片的url網絡鏈接(http://) 轉為base64格式2&#xff0c;將base64的圖片數據轉換為file文件3&#xff0c;將以base64的圖片數據轉換為Blob4&#xff0c;將file文件轉化為base645&#xff0c;將file文件轉換為Blob6&#xff0c;獲取文…

CentOS系統環境搭建(八)——CentOS7開機自動執行腳本(以MySQL為例)

CentOS7開機自動執行腳本 文章目錄 CentOS7開機自動執行腳本第一步&#xff1a;新建一個腳本run.sh第二步&#xff1a;腳本添加可執行權限第三步&#xff1a;執行如下命令將/etc/rc.d/rc.local文標記為可執行文件第四步&#xff1a;打開/etc/rc.d/rc.local文件&#xff0c;在最…

利用Opencv實現人像遷移

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天來學習一下如何使用Opencv實現人像遷移&#xff0c;歡迎大家一起參與探討交流~ 本文目錄&#xff1a; 一、實驗要求二、實驗環境三、實驗原理及操作1.照片準備2.圖像增強3.實現美顏功能4.背景虛化5.圖像二值化處理6.人…

item_password-獲得淘口令真實url

一、接口參數說明&#xff1a; item_password-獲得淘口令真實url &#xff0c;點擊更多API調試&#xff0c;請移步注冊API賬號點擊獲取測試key和secret 公共參數 請求地址: https://api-gw.onebound.cn/taobao/item_password 名稱類型必須描述keyString是調用key&#xff08…

tomcat源碼修改與編譯

1、獲取源碼 從github下載其源碼&#xff1a;https://github.com/apache/tomcat 2、選擇版本 切換到對應版本&#xff08;直接用相對應的Git tag即可&#xff09;&#xff1a; git checkout 9.0.793、修改源代碼&#xff0c;并且生成補丁 這里我們以修改去掉新版本的ws的檢…

129.【Spring 注解 IOC】

Spring 注解 (一)、組件注冊1. Configuration 與 Bean 容器注冊組件(1).無注解注入方式(2).注解注入方式 2. ComponentScan 自動掃描組件和自動掃描規則(1).無注解掃描方式(2).注解掃描注入方式(3).指定掃描或不掃描的包 (過濾) 3. 自定義TypeFilter指定過濾規則 Filter(1).自定…

openCV項目開發實戰--詳細介紹如何改善夜間圖像的照明(附python和C++源碼)

文末附完整的代碼實現下載鏈接 介紹 對于非攝影師來說,在光線不佳的條件下拍出好照片似乎很神奇。完成低光攝影需要技巧、經驗和正確的設備的結合。在弱光下拍攝的圖像缺乏色彩和獨特的邊緣。它們還遭受能見度差和深度未知的困擾。這些缺點使得此類圖像不適合個人使用或圖像處…

QT多屏顯示程序

多屏顯示的原理其實很好理解&#xff0c;就拿橫向擴展來說&#xff1a; 計算機把桌面的 寬度擴展成了 w1&#xff08;屏幕1的寬度&#xff09; w2(屏幕2的寬度) 。 當一個窗口的起始橫坐標 > w1&#xff0c;則 他就被顯示在第二個屏幕上了。 drm設備可以多用戶同時打開&am…

Spring MVC 簡介

目錄 1. 什么是MVC2. 什么是SpringMVC 1. 什么是MVC MVC是一種常用的軟件架構模式。可以看作是一種設計模式&#xff0c;也可以看作是一種軟件框架。經典MVC模式中&#xff0c;M是指模型&#xff0c;V是視圖&#xff0c;C則是控制器&#xff0c;使用MVC的目的是將M和V的實現代…

golang中使用chan控制協程并發簡單事例

func main() {processNum : 5ch : make(chan struct{}, processNum)for true {ch <- struct{}{}go func() {defer func() {<-ch}()fmt.Println("我是協程", time.Now().UnixNano())time.Sleep(time.Second * 5)}()} } 可以看到&#xff0c;這里每5s會執行一次帶…

Linux15 消息隊列 線程

目錄 1、進程間通信IPC&#xff1a; 2、多線程 3、向消息隊列中寫入數據 4、從消息隊列中讀取數據 5、多線程&#xff1a; 6、將多線程的數據返回給主…

數據庫索引優化策略與性能提升實踐

文章目錄 什么是數據庫索引&#xff1f;為什么需要數據庫索引優化&#xff1f;數據庫索引優化策略實踐案例&#xff1a;索引優化帶來的性能提升索引優化規則1. 前導模糊查詢不適用索引2. 使用IN優于UNION和OR3. 負向條件查詢不適用索引4. 聯合索引最左前綴原則5. 范圍條件查詢右…

c#實現策略模式

下面是一個使用C#實現策略模式的示例代碼&#xff1a; using System;// 策略接口 public interface IStrategy {void Execute(); }// 具體策略類A public class ConcreteStrategyA : IStrategy {public void Execute(){Console.WriteLine("具體策略A的執行邏輯");} …