函數模板和類模板

函數模板也可以提前聲明,不過聲明時需要帶上模板頭,並且模板頭和函數定義(聲明)是一個不可分割的整體,它們可以換行,但中間不能有分號

類模板,在類外定義成員函數時不僅要加模板頭,在類名的後面還有加上類型參數
例如:

template<typename T1, typename T2>
void Point<T1, T2>::setX(T1 x){
    m_x = x;
}

類模板在實例化時(創建對象時)必須顯式地指明數據類型,編譯器不能根據給定的數據推演出數據類型

函數模板常重載

函數模板和普通函數一樣可以重載
類模板創建對象時需要顯示指明實參類型,函數模板則不需要,那麼函數模板的實參是如何推斷出來的呢?

模板實參推斷過程中的類型轉換

普通函數調用時的參數轉換包括:

  • 算術轉換 int轉float char 轉int
  • 派生類向基類轉換
  • const轉換
  • 數組和數組指針轉換
    模板函數只能進行的轉換:
  • 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);//error
由於 str1、str2 的類型分別爲 int [20]int [10],
在函數調用過程中又不會轉換爲指針,所以編譯器不知道應該將 T 實例化爲 int [20]
還是 int [10],導致調用失敗。

爲函數模板顯式地指明實參

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

template<typename T1, typename T2> void func(T1 a){
    T2 b;
}
調用時只有一個參數T1,無法確定T2的類型,因此需要對T2指明實參,
因爲T2是第二個參數,所以同時也要對第一個參數T1指明實參

template<typename T1, typename T2> void func(T2 a){
    T1 b;
}
調用時只有一個參數T2,無法確定T1的類型,因此需要對T1指明實參,
因爲T2是第二個參數,所以可以只指明第一個實參T1,T2可以自動推斷出來
可以省略

顯示指明實參可以進行類型轉換

template<typename T> void func(T a, T b);
func(10, 23.5);  //Error
不知道把int轉爲float還是把float轉爲int 

func<float>(20, 93.7);  //Correct
顯示指明轉爲float
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章