泛型編程概念:不考慮具體數據類型的編程方式;
函數模板:
1.提供一種特殊的函數可用不同類型進行調用;
2.與普通函數很相似,區別是類型可被參數化;
template <typename T> //template關鍵字用於聲明開始進行泛型編程
void Swap(T &a, T &b) //typename關鍵字用於聲明泛指類型
{
T tmp = a;
a = b;
b = tmp;
}
函數模板的應用:
1.自動類型推導調用;
2.具體類型顯示調用;
int a = 3; int b = 4; Swap(a,b); //自動類型推導調用 float fa = 5.5; float fb = 8.8; Swap<float>(fa, fb) //具體類型顯示調用,用float替換參數類型T
使用演示:
#include <iostream>
template <typename T> //交換變量
void Swap(T& a, T& b)
{
T t;
t = a;
a = b;
b = t;
}
template <typename T> //將數組內容從小到大排序
void SelectMin(T array[], int size)
{
for (int i = 0; i < size; i++)
{
T Min = array[i];
int Index = 1;
for (int j = i + 1; j < size; j++)
{
if (Min > array[j])
{
Min = array[j];
Index = j;
Swap(array[i], array[Index]);
}
}
}
}
int main()
{
int a = 3;
int b = 8;
Swap(a, b); //自動類型推導
std::cout << "a = " << a << std::endl;
std::cout << "b = " << b << std::endl;
float fa = 3.4;
float fb = 8;
Swap<float>(fa, fb); //具體類型顯示調用
std::cout << "fa = " << fa << std::endl;
std::cout << "fb = " << fb << std::endl;
char ca = 'a';
char cb = 'b';
Swap(ca, cb);
std::cout << "ca = " << ca << std::endl;
std::cout << "cb = " << cb << std::endl;
int array[] = {4, 3, 1, 2, 45};
SelectMin(array, 5);
for (int i = 0; i < 5; i++)
{
std::cout << "i = " << array[i] << std::endl;
}
char array2[] = { 'a', 'f', 'e', 'c', 'b' };
SelectMin(array2, 5);
for (int i = 0; i < 5; i++)
{
std::cout << "i = " << array2[i] << std::endl;
}
return 0;
}
函數模板的深入理解:
-- 編譯器並不會把函數模板處理成能夠處理任意類型的函數;
--編譯器從函數模板通過具體類型產生不同的函數;
--編譯器會對函數模板進行兩次編譯;
--在聲明的地方對模板代碼本身進行編譯
--在調用的地方對參數替換后的代碼進行編譯
當函數模板遇到函數重載:
--C++編譯器優先考慮普通函數;
--如果函數模板可以產生一個更好的匹配,那么選擇模板;
--通過空模板實參列表的語法限定編譯器只通過模板匹配;
注意事項:
--函數模板不允許自動類型轉化;
--普通函數能夠進行類型轉化;
int Max(int a, int b) //普通函數
{
return a > b ? a : b;
}
template <typename T> //模板函數
T Max(T a, T b)
{
return a > b ? a : b;
}
int main()
{
int a = 4;
int b = 8;
Max(a,b); //調用普通函數
Max<>(a,b); //空模板實參列表,只能調用函數模板
float fa = 5.5;
float fb = 8.8;
Max(fa,fb); //調用普通函數會進行類型轉換,通過函數模板會產生一個更好的匹配
Max('a',100);//返回結果是調用普通函數a的ASCII碼,因為‘a’是字符型,100是整形,與函數模板不匹配
return 0;
}
函數模板可以定義多個類型的參數:
template <typename T1, typename T2, typename RT>
RT Add(T1 a, T2 b) //RT作為返回類型
{
return static_cast<RT>(a+b)
}
cout<<Add<char, float, double>('a', 100)<<endl;
當聲明的類型參數作為返回值類型,無法推導出返回值類型!
即Add('a', 100)這樣自動推導調用編譯器會報錯;
不完美處理方案:
template <typename RT, typename T1, typename T2>
RT Add(T1 a, T2 b) //RT作為返回類型
{
return static_cast<RT>(a+b)
}
cout<<Add<double>('a', 100)<<endl; //將返回類型放在第一個參數,只顯示的列出返回值類型,其它2個參數編譯器自動推導
