網站首頁 編程語言 正文
? ? 結合網上的資料,對函數模板的重載與實參推斷做一個總結。
函數模板的重載
? 當需要對不同的類型使用同一種算法時,為了避免定義多個功能重復的函數,可以使用模板。然而,并非所有的類型都使用同一種算法,有些特定的類型需要單獨處理,為了滿足這種需求,C++允許對函數模板進行重載。
? 例如,當交換基本類型和交換兩個數組時,雖然功能都是交換,但是使用的方法卻不相同,交換兩個數組唯一的辦法就是逐個交換所有的數組元素。
template<class T> void Swap(T &a, T &b){
T temp = a;
a = b;
b = temp;
}
template<typename T> void Swap(T a[], T b[], int len){
T temp;
for(int i=0; i<len; i++){
temp = a[i];
a[i] = b[i];
b[i] = temp;
}
}
函數模板的實參
? 在使用類模板創建對象時,需要顯式的指明實參,例如:
template<typename T1, typename T2> class Point;
Point<int, int> p1(10, 20); //在棧上創建對象
Point<char*, char*> *p = new Point<char*, char*>("東京180度", "北緯210度"); //在堆上創建對象
對于函數模板,調用函數時可以不顯式的指明實參,編譯器會自動推導出T的類型,例如:
//函數聲明
template<typename T> void Swap(T &a, T &b);
//函數調用
int n1 = 100, n2 = 200;
Swap(n1, n2);
float f1 = 12.5, f2 = 56.93;
Swap(f1, f2);
模板實參推斷過程中的類型轉換
普通函數調用時的類型轉換
- 算數轉換:例如 int 轉換為 float,char 轉換為 int,double 轉換為 int 等。
- 派生類向基類的轉換:也就是向上轉型,
- const 轉換:也即將非 const 類型轉換為?const 類型,例如將 char * 轉換為 const char *。
- 數組或函數指針轉換:如果函數形參不是引用類型,那么數組名會轉換為數組指針,函數名也會轉換為函數指針。
- 用戶自定的類型轉換。
例如:
void func1(int n, float f);
void func2(int *arr, const char *str);
int nums[5];
char *url = "http://c.biancheng.net";
func1(12.5, 45);
func2(nums, url);
? 對于 func1(),12.5 會從double
轉換為int
,45 會從int
轉換為float
;對于 func2(),nums 會從int [5]
轉換為int *
,url 會從char *
轉換為const char *
。
函數模板調用時的類型轉換
? 對于函數模板,類型轉換收到了更多的限制,僅能進行[const 轉換]和[數組或函數指針轉換],其他都不能應用于函數模板。
template<typename T> void func1(T a, T b);
template<typename T> void func2(T *buffer);
template<typename T> void func3(const T &stu);
template<typename T> void func4(T a);
template<typename T> void func5(T &a);
int name[20];
Student stu1("張華", 20, 96.5); //創建一個Student類型的對象
func1(12.5, 30); //Error
func2(name); //name的類型從 int [20] 換轉換為 int *,所以 T 的真實類型為 int
func3(stu1); //非const轉換為const,T 的真實類型為 Student
func4(name); //name的類型從 int [20] 換轉換為 int *,所以 T 的真實類型為 int *
func5(name); //name的類型依然為 int [20],不會轉換為 int *,所以 T 的真實類型為 int [20]
可以發現,當函數形參是引用類型時,數組不會轉換為指針。
template<typename T> void func(T &a, T &b);
int str1[20];
int str2[10];
func(str1, str2);
? 由于str1、str2的類型分別為int [20]和int [10],在函數調用過程中又不會轉換為指針,所以編譯器不知道應該將T實例化為int [20]還是int [10],導致調用失敗
為函數模板顯式地指明實參
? 下面是一個實參推斷失敗的例子:
template<typename T1, typename T2> void func(T1 a){
T2 b;
}
func(10); //函數調用
func()有兩個類型參數,分別是T1和T2,但是編譯器只能推斷出T1,不能推斷出T2,調用失敗
? 顯示指明的模板實參會按照從左到右的順序與對應的模板參數匹配:第一個實參與第一個模板參數匹配,第二個實參與第二個模板參數匹配,只有尾部(最右)的類型參數的實參可以省略,而且前提是它們可以從傳遞給函數的實參中推斷出來。 例如:
template<typename T1, typename T2> void func(T2 a){
T1 b;
}
//函數調用
func<int>(10); //省略 T2 的類型
func<int, int>(20); //指明 T1、T2 的類型
顯式的指明實參時可以應用正常的類型轉換
? 函數模板僅能進行[ const 轉換 ]和[ 數組或函數指針轉換 ]兩種形式的類型轉換,但是當我們顯式的指明類型參數的實參時,就可以使用正常的類型轉換了。例如:
template<typename T> void func(T a, T b);
func(10, 23.5); //Error
func<float>(20, 93.7); //Correct
? 在第二種調用形式中,我們已經顯式地指明了T的類型為float,編譯器不會再為T的類型到底是int還是double而糾結了,所以可以從容地使用正常地類型轉換了。
原文鏈接:https://blog.csdn.net/weixin_45767431/article/details/127574432
- 上一篇:C++ 模板的顯式具體化
- 下一篇:C++通過Makefile定義宏參數,傳入程序
相關推薦
- 2023-07-16 unipp 小程序 退出登錄
- 2022-03-22 C語言return,?exit,?abort的區別_C 語言
- 2022-09-30 centos7安裝docker容器的超詳細步驟記錄_docker
- 2023-11-20 Linux/樹莓派如何限制CPU使用率?cpulimit的基本用法
- 2023-05-07 Python3中省略號(...)用法介紹_python
- 2022-12-09 Opencv中的cv2.calcHist()函數的作用及返回值說明_python
- 2022-01-19 錯誤:Cannot construct instance of `xxxx` (no Creator
- 2022-05-12 Kotlin any/none/all 函數
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支