函式模板、函式模板例項化、函式模板過載
阿新 • • 發佈:2018-10-31
模板是泛型程式設計的基礎。所謂泛型程式設計就是編寫與型別無關的邏輯程式碼,是一種複用的方式。模板分為模板函式和模板類。
如果是交換兩個資料,我們會定義對應型別的函式,比如要交換int型別資料,我們會定義int型別swap函式,如果是交換double型別資料,會再定義double型別交換函式。
void Swap(int& a, int &b)
{
int c = a;
a = b;
b = c;
}
void Swap(double& a, double &b)
{
double c = a;
a = b;
b = c;
}
這樣重複定義函式,程式碼重複度十分高,但是模板來說不需要使用者自己定義多種型別的函式,只需要定義一個模板就可以。模板分為函式模板和類模板。
函式模板
函式模板代表了一個函式家族,該函式模板與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本
函式模板格式
template<typename 形參名1,typename 形參名2,typename形參名3>
返回型別 函式名(引數列表)
{…}
模板引數的定義既可以用typename,也可以用class(但是不能用struct),含義是相同的
template<typename T> //模板引數的定義 void Swap( T& a, T& b) { T c = a; a = b; b = c; //沒有例項化不會報錯 } 如果函式模板內部出現錯誤,編譯期間將不會報錯,因為是在例項化時才檢查模板內容,即當用Swap(a,b)會檢查模板內容 但是當函式模板頭出現問題時,會立即報錯
int main()
{
int a = 1, b = 2;
double c = 2.2, d = 3.4;
Swap(a, b);
Swap(c, d);
cout << a << endl << b << endl;
cout << c << endl << d << endl;
system("pause");
return 0;
}
彙編看函式模板例項化過程:
模板引數的原理:
模板本身不是類或函式,編譯器用模板產生指定的類或函式的特定型別版本,產生模板特定型別的過程稱為函式的模板例項化。
在使用函式模板時,編譯器需要根據傳入的實參型別,推演生成對應型別的函式來使用。
比如int型別使用函式模板時,編譯器通過對實參型別的推演,將確定為int型別,最後會生成int型別的資料交換函式
函式模板的例項化
用不同型別的引數使用函式模板時稱為函式模板的例項化,模板引數例項化分為隱式例項化和顯示例項化
template<typename T>
T Add(T a, T b)
{
return a + b;
}
int main()
{
int a = 1, b = 2;
double c = 2.2, d = 3.4;
//cout << Add(a, d) << endl;
//在編譯期間,當編譯器看到該例項化時,需要推演實參型別,通過第一個引數a將T推演為int,
//第二個推演為double,但是,模板引數型別只有一個T,編譯器無法確定將T推演為int或者double而出錯
//因此需要將型別轉換為相同的,可以使用者自己強轉即隱式型別轉換,也可以用顯示型別轉換
//隱式型別轉換
cout << Add(a, b) << endl; //2
cout << Add(a, (int)d) << endl;//4
cout << Add((double)a, d) << endl; //4.4
//顯示型別轉換:在函式名後加<具體型別>
cout << Add<int>(a, d) << endl; //4
system("pause");
return 0;
}
函式模板過載
template<typename T>
T Add(T a, T b)
{
return a + b;
}
int Add(int a, int b)
{
return a + b;
}
template<typename T1,typename T2>
T2 Add(T1 a, T2 b)
{
return a + b;
}
int main()
{
int a = 1, b = 2;
cout << Add(a, b) << endl; //int Add(int a, int b),如果有現成函式就不用模板
double c = 1.2, d = 3.5;
//根據引數找不同模板例項化
cout << Add(c, d) << endl; //T Add(T a, T b)
cout << Add(a, d) << endl; //T2 Add(T1 a, T2 b)
system("pause");
return 0;
}