1.什麼是函數模版 函數模板,實際上是建立一個通用函數,其函數類型和形參類型不具體制定,用一個虛擬的類型來代表。這個通用函數就成為函數模板 2.怎麼編寫函數模版 //T代表泛型的數據類型,不是只能寫T, template<class T>//讓編譯器看到這句話後面緊跟著的函數里有T不要報錯 void ...
1.什麼是函數模版
函數模板,實際上是建立一個通用函數,其函數類型和形參類型不具體制定,用一個虛擬的類型來代表。這個通用函數就成為函數模板
2.怎麼編寫函數模版
//T代表泛型的數據類型,不是只能寫T,
template<class T>//讓編譯器看到這句話後面緊跟著的函數里有T不要報錯
void mySwap(T &a,T &b)
{
T tmp = a;
a = b;
b = tmp;
}
//可以這樣定義函數模版
template<typename T>
void func2(T a,T b)
{
}
3.怎麼使用函數模版
//T代表泛型的數據類型,不是只能寫T,
template<class T>//讓編譯器看到這句話後面緊跟著的函數里有T不要報錯
void mySwap(T &a,T &b)
{
T tmp = a;
a = b;
b = tmp;
}
template<class T>
void mySwap2()
{
}
//使用函數模版
void test02()
{
int a = 10;
int b = 20;
//1.編譯器會根據實參來自動推導數據類型
mySwap(a,b);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
char c = 'c';
//mySwap(a, c);err,數據類型要一致
//2.顯示的指定類型
mySwap<int>(a, b);//<>用參數列表告訴編譯器我只傳int類
//mySwap<double>(a, b);//註意:指定類型,傳入時不能不一致
mySwap<>(a,b);
//mySwap2<>();//err 調用時,必須讓編譯器知道泛型T具體是什麼類型
}
4.編譯器會對函數模版和類模版進行二次編譯
//T代表泛型的數據類型,不是只能寫T,
template<class T>//讓編譯器看到這句話後面緊跟著的函數里有T不要報錯
void mySwap(T &a,T &b)//第一次編譯
{
T tmp = a;
a= b;
b = tmp;
}
//使用函數模版
void test02()
{
int a = 10;
int b = 20;
//1.編譯器會根據實參來自動推導數據類型
mySwap(a,b);//編譯器在函數模版被調用時,進行第二次編譯
/*
void mySwap(int &a,int &b)
{
int tmp = a;
a= b;
b = tmp;
}
*/
cout << "a=" << a << endl;
cout << "b=" << b << endl;
}
5.隱式轉換
template<class T>
T func(T a, T b)
{
return a + b;
}
void test03()
{
int a = 10;
double b = 20.2;
//如果使用參數列表指定數據類型,那麼實參中可以隱式轉換
//如果轉換成功,就調用,轉換不成功就報錯
cout << func<int>(10,20.2) << endl;
}
6.函數模板和普通函數的區別
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//普通函數
int myPlus(int a, int b)
{
return a + b;
}
template<class T>
int myPlus2(T a, T b)
{
return a + b;
}
void test()
{
int a = 10;
int b = 20;
char c = 'a';
//普通函數可以進行隱式轉換
myPlus(a, c);
//函數模版不能直接的進行隱式轉換
//myPlus2(a, c);
myPlus2<int>(a, c);//如果要進行隱性轉換,必須加上參數列表
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
7.普通函數和函數模版的調用規則
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//普通函數
void myPlus(int a, int b)
{
cout << "普通函數" << endl;
}
template<class T>
void myPlus(T a, T b)
{
cout << "函數模版" << endl;
}
template<class T>
void myPlus(T a, T b, T c)
{
cout << "函數模版 T c" << endl;
}
//1.函數模版和普通函數可以重載
void test()
{
int a = 10;
int b = 20;
//2.如果普通函數和函數模版都可以實現的功能,普通函數優先調用
myPlus(a, b);
//3.可以使用<>空參數列表強制調用函數模版
myPlus<>(a, b);
//4.函數模版之間也可以進行重載
//5.如果函數模版可以產生更好的匹配,那麼優先使用函數模版
char c1 = 'a';
char c2 = 'b';
myPlus(c1, c2);
}
int main()
{
test();
system("pause");
return EXIT_SUCCESS;
}
8.函數模版的局限性和解決方法
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<string>
template<class T>
void func(T a, T b)
{
if (a > b)
{
cout << "a>b" << endl;
}
else
{
cout << "a<=b" << endl;
}
}
void test()
{
int arr[20];
int arr2[10];
func(arr, arr2);
}
class Maker
{
public:
Maker(string name,int age)
{
this->age = age;
this->name = name;
}
public:
string name;
int age;
};
template<class T>
void myfunc(T &a, T &b)
{
if (a > b)
{
cout << "a>b" << endl;
}
else
{
cout << "a<=b" << endl;
}
}
//不建議具體化函數模版,因為沒有通用性
//具體化函數模版,註意上面的函數模版要有,才能具體化
template<>void myfunc<Maker>(Maker &a, Maker &b)
{
cout << "函數模版的具體化" << endl;
if (a.age > b.age)
{
cout << "a>b" << endl;
}
else
{
cout << "a<=b" << endl;
}
}
void test02()
{
Maker m1("aaa", 10);
Maker m2("bbb", 20);
myfunc(m1, m2);
}
int main()
{
test02();
system("pause");
return EXIT_SUCCESS;
}
參考資料
參考資料來源於黑馬程式員