日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達(dá)者為師

網(wǎng)站首頁 編程語言 正文

C++ 函數(shù)模板的重載與實(shí)參推斷

作者:weixin_45767431 更新時間: 2022-10-29 編程語言

? ? 結(jié)合網(wǎng)上的資料,對函數(shù)模板的重載與實(shí)參推斷做一個總結(jié)。

函數(shù)模板的重載

? 當(dāng)需要對不同的類型使用同一種算法時,為了避免定義多個功能重復(fù)的函數(shù),可以使用模板。然而,并非所有的類型都使用同一種算法,有些特定的類型需要單獨(dú)處理,為了滿足這種需求,C++允許對函數(shù)模板進(jìn)行重載。

? 例如,當(dāng)交換基本類型和交換兩個數(shù)組時,雖然功能都是交換,但是使用的方法卻不相同,交換兩個數(shù)組唯一的辦法就是逐個交換所有的數(shù)組元素。

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;
    }
}

函數(shù)模板的實(shí)參

? 在使用類模板創(chuàng)建對象時,需要顯式的指明實(shí)參,例如:

template<typename T1, typename T2> class Point;
Point<int, int> p1(10, 20);  //在棧上創(chuàng)建對象
Point<char*, char*> *p = new Point<char*, char*>("東京180度", "北緯210度");  //在堆上創(chuàng)建對象

對于函數(shù)模板,調(diào)用函數(shù)時可以不顯式的指明實(shí)參,編譯器會自動推導(dǎo)出T的類型,例如:

//函數(shù)聲明
template<typename T> void Swap(T &a, T &b);
//函數(shù)調(diào)用
int n1 = 100, n2 = 200;
Swap(n1, n2);
float f1 = 12.5, f2 = 56.93;
Swap(f1, f2);

模板實(shí)參推斷過程中的類型轉(zhuǎn)換

普通函數(shù)調(diào)用時的類型轉(zhuǎn)換

  • 算數(shù)轉(zhuǎn)換:例如 int 轉(zhuǎn)換為 float,char 轉(zhuǎn)換為 int,double 轉(zhuǎn)換為 int 等。
  • 派生類向基類的轉(zhuǎn)換:也就是向上轉(zhuǎn)型,
  • const 轉(zhuǎn)換:也即將非 const 類型轉(zhuǎn)換為?const 類型,例如將 char * 轉(zhuǎn)換為 const char *。
  • 數(shù)組或函數(shù)指針轉(zhuǎn)換:如果函數(shù)形參不是引用類型,那么數(shù)組名會轉(zhuǎn)換為數(shù)組指針,函數(shù)名也會轉(zhuǎn)換為函數(shù)指針。
  • 用戶自定的類型轉(zhuǎn)換。

例如:

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轉(zhuǎn)換為int,45 會從int轉(zhuǎn)換為float;對于 func2(),nums 會從int [5]轉(zhuǎn)換為int *,url 會從char *轉(zhuǎn)換為const char *

函數(shù)模板調(diào)用時的類型轉(zhuǎn)換

? 對于函數(shù)模板,類型轉(zhuǎn)換收到了更多的限制,僅能進(jìn)行[const 轉(zhuǎn)換]和[數(shù)組或函數(shù)指針轉(zhuǎn)換],其他都不能應(yīng)用于函數(shù)模板。

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);  //創(chuàng)建一個Student類型的對象
func1(12.5, 30);  //Error
func2(name);  //name的類型從 int [20] 換轉(zhuǎn)換為 int *,所以 T 的真實(shí)類型為 int
func3(stu1);  //非const轉(zhuǎn)換為const,T 的真實(shí)類型為 Student
func4(name);  //name的類型從 int [20] 換轉(zhuǎn)換為 int *,所以 T 的真實(shí)類型為 int *
func5(name);  //name的類型依然為 int [20],不會轉(zhuǎn)換為 int *,所以 T 的真實(shí)類型為 int [20]

可以發(fā)現(xiàn),當(dāng)函數(shù)形參是引用類型時,數(shù)組不會轉(zhuǎn)換為指針。

template<typename T> void func(T &a, T &b);

int str1[20];
int str2[10];
func(str1, str2);

? 由于str1、str2的類型分別為int [20]和int [10],在函數(shù)調(diào)用過程中又不會轉(zhuǎn)換為指針,所以編譯器不知道應(yīng)該將T實(shí)例化為int [20]還是int [10],導(dǎo)致調(diào)用失敗

為函數(shù)模板顯式地指明實(shí)參

? 下面是一個實(shí)參推斷失敗的例子:

template<typename T1, typename T2> void func(T1 a){
    T2 b;
}
func(10);  //函數(shù)調(diào)用

func()有兩個類型參數(shù),分別是T1和T2,但是編譯器只能推斷出T1,不能推斷出T2,調(diào)用失敗

? 顯示指明的模板實(shí)參會按照從左到右的順序與對應(yīng)的模板參數(shù)匹配:第一個實(shí)參與第一個模板參數(shù)匹配,第二個實(shí)參與第二個模板參數(shù)匹配,只有尾部(最右)的類型參數(shù)的實(shí)參可以省略,而且前提是它們可以從傳遞給函數(shù)的實(shí)參中推斷出來。 例如:

template<typename T1, typename T2> void func(T2 a){
    T1 b;
}
//函數(shù)調(diào)用
func<int>(10);  //省略 T2 的類型
func<int, int>(20);  //指明 T1、T2 的類型

顯式的指明實(shí)參時可以應(yīng)用正常的類型轉(zhuǎn)換

? 函數(shù)模板僅能進(jìn)行[ const 轉(zhuǎn)換 ]和[ 數(shù)組或函數(shù)指針轉(zhuǎn)換 ]兩種形式的類型轉(zhuǎn)換,但是當(dāng)我們顯式的指明類型參數(shù)的實(shí)參時,就可以使用正常的類型轉(zhuǎn)換了。例如:

template<typename T> void func(T a, T b);
func(10, 23.5);  //Error
func<float>(20, 93.7);  //Correct

? 在第二種調(diào)用形式中,我們已經(jīng)顯式地指明了T的類型為float,編譯器不會再為T的類型到底是int還是double而糾結(jié)了,所以可以從容地使用正常地類型轉(zhuǎn)換了。

原文鏈接:https://blog.csdn.net/weixin_45767431/article/details/127574432

欄目分類
最近更新