1. 函數(shù)模板
概念:
函數(shù)模板代表了一個函數(shù)家族,該函數(shù)模板與類型無關,在使用時被參數(shù)化,根據(jù)實參類型產(chǎn)生函數(shù)的特定類型版本。
具體格式:
template<typename T1, typename T2,…,typename Tn>
返回值類型 函數(shù)名(參數(shù)列表){}
#include <iostream>
using namespace std;
template <class T>
void func(T& num) {
cout << num << endl;
}
int main() {
int a = 1;
double b = 1.2;
string c = "1.3";
func(a);
func(b);
func(c);
return 0;
}
輸出結果:
typename是用來定義模板參數(shù)關鍵字,也可以使用class(切記:不能使用struct代替class)
函數(shù)模板是一個藍圖,它本身并不是函數(shù),是編譯器用使用方式產(chǎn)生特定具體類型函數(shù)的模具。所以其實模
板就是將本來應該我們做的重復的事情交給了編譯器。
函數(shù)模板的實例化
template <typename T>
void add(const T& a, const T& b) {
cout << a + b << endl;
}
int main() {
int a1 = 1, a2 = 2;
double b1 = 1.2, b2 = 1.3;
add(a1, a2);
add(b1, b2);
//編譯錯誤
add(a1, b1);
return 0;
}
上面模板參數(shù)列表中只有一個T,編譯器無法確定到底將T確定為int還是double類型,所以報錯。
有兩種處理方法,一是用戶自己強制轉化類型,二是使用顯示實例化。
template <typename T>
void add(const T& a, const T& b) {
cout << a + b << endl;
}
int main() {
int a1 = 1, a2 = 2;
double b1 = 1.2, b2 = 1.3;
add(a1, a2);
add(b1, b2);
add(a1, (int)b1);
return 0;
}
輸出結果:
顯示實例化
顯示實例化就是在函數(shù)名后的<>中指定模板參數(shù)的實際類型。
template <typename T>
void add(const T& a, const T& b) {
cout << a + b << endl;
}
int main() {
int a1 = 1, a2 = 2;
double b1 = 1.2, b2 = 1.3;
add<int>(a1, b2);
return 0;
}
輸出結果:
要是類型不匹配,編譯器會嘗試進行隱式類型轉換,如果無法轉換成功編譯器將會報錯。
模板參數(shù)的匹配原則
- 一個非模板函數(shù)可以和一個同名的函數(shù)模板同時存在,而且該函數(shù)模板還可以被實例化為這個非模板函數(shù)
void add(int a, int b) {
cout << a + b << endl;
}
template <typename T>
void add(const T& a, const T& b) {
cout << a + b << endl;
}
int main() {
int a1 = 1, a2 = 2;
double b1 = 1.2, b2 = 1.3;
add(a1, a2);
add<int>(a1, a2);
return 0;
}
- 對于非模板函數(shù)和同名函數(shù)模板,如果其他條件都相同,在調(diào)動時會優(yōu)先調(diào)用非模板函數(shù)而不會從該模板產(chǎn)生出一個實例。如果模板可以產(chǎn)生一個具有更好匹配的函數(shù), 那么將選擇模板。
void add(int a, int b) {
cout << a + b << endl;
}
template <typename T>
void add(const T& a, const T& b) {
cout << a + b << endl;
}
int main() {
int a1 = 1, a2 = 2;
double b1 = 1.2, b2 = 1.3;
add(a1, a2);
add<int>(a1, b1);
return 0;
}
- 模板函數(shù)不允許自動類型轉換,但普通函數(shù)可以進行自動類型轉換
2. 類模板
類模板的定義格式
template<class T1, class T2, ..., class Tn>
class 類模板名
{
// 類內(nèi)成員定義
};
類模板的實例化
類模板實例化與函數(shù)模板實例化不同,也就是說類模板實例化不支持隱式實例化,**類模板實例化需要在類模板名字后跟<>,然后將實例化的類型放在<>中即可,**類模板名字不是真正的類,而實例化的結果才是真正的類。
3. 非類型模板參數(shù)
模板參數(shù)分類類型形參與非類型形參。
- 類型形參即:出現(xiàn)在模板參數(shù)列表中,跟在class或者typename之類的參數(shù)類型名稱。
- 非類型形參,就是用一個常量作為類(函數(shù))模板的一個參數(shù),在類(函數(shù))模板中可將該參數(shù)當成常量來用。
const int N = 10;
template<class T>
class array
{
private:
T a[N];
};
int main()
{
array<int> a1;
array<double> a2;
return 0;
}
上面有兩個數(shù)組,但是我想讓他們的大小各不相同(a1大小為10,a2大小為100),該如何做呢?
template<class T,size_t N = 10>
class array
{
private:
T a[N];
};
int main()
{
array<int,10> a1;
array<double,100> a2;
return 0;
}
這時候非類型模板參數(shù)就起到了作用。
注意!
- 浮點數(shù)、類對象以及字符串是不允許作為非類型模板參數(shù)的。
- 非類型的模板參數(shù)必須在編譯期就能確認結果。也就是說你不能在前面定義個變量num,然后傳進去用。
4. 模板的特化
4.1. 函數(shù)模板的特化
template<class T>
bool func(T a, T b)
{
return a < b;
}
int main()
{
int a = 1, b = 2;
char c = 3, d = 0;
cout << func(a, b) << endl;
cout << func(c, d) << endl;
return 0;
}
輸出結果:
在大多數(shù)情況下,上述代碼都可以實現(xiàn)想要的結果,但是針對特殊類型,假如是指針類型,該如何做呢?
template<class T>
bool func(T a, T b)
{
return a < b;
}
int main()
{
int a = 1, b = 2;
char c = 3, d = 0;
cout << func(a, b) << endl;
cout << func(c, d) << endl;
cout << func(&a, &b) << endl;
return 0;
}
輸出結果:
此時,就要對模板進行特化。即:在原模板類的基礎上,針對特殊類型所進行特殊化的實現(xiàn)方式。
特化步驟:
- 必須要先有一個基礎的函數(shù)模板
- 關鍵字template后面接一對空的尖括號<>
- 函數(shù)名后跟一對尖括號,尖括號中指定需要特化的類型
- 函數(shù)形參表: 必須要和模板函數(shù)的基礎參數(shù)類型完全相同,如果不同編譯器可能會報一些奇怪的錯誤。
template<class T>
bool func(T a, T b)
{
return a < b;
}
template<>
bool func<int*>(int* a, int* b)
{
return *a < *b;
}
int main()
{
int a = 1, b = 2;
char c = 3, d = 0;
cout << func(a, b) << endl;
cout << func(c, d) << endl;
cout << func(&a, &b) << endl;
return 0;
}
輸出結果:
4.2. 類模板特化
4.2.1. 全特化
template<class T1,class T2>
class test
{
public:
test()
{
cout << "(T1,T2)" << endl;
}
private:
T1 a;
T2 b;
};
template<>
class test<double,float>
{
public:
test()
{
cout << "(double,float)" << endl;
}
private:
double a;
float b;
};
int main()
{
test<int,int> t1; //調(diào)用基礎的模板
test<double, float> t2; //調(diào)用特化的版本
return 0;
}
全特化就是將模板參數(shù)列表中所有的參數(shù)都確定化
4.2.2. 偏特化
- 部分特化
template<class T1,class T2>
class test
{
public:
test()
{
cout << "(T1,T2)" << endl;
}
private:
T1 a;
T2 b;
};
template<class T1>
class test<T1,int>
{
public:
test()
{
cout << "(T1,int)" << endl;
}
private:
T1 a;
int b;
};
int main()
{
test<int,int> t1; //調(diào)用基礎的模板
test<double, int> t2;//調(diào)用特化的模板
return 0;
}
偏特化并不僅僅是指特化部分參數(shù),而是針對模板參數(shù)更進一步的條件限制所設計出來的一個特化版文章來源:http://www.zghlxwxcb.cn/news/detail-556475.html
本。文章來源地址http://www.zghlxwxcb.cn/news/detail-556475.html
template<class T1,class T2>
class test
{
public:
test()
{
cout << "(T1,T2)" << endl;
}
private:
T1 a;
T2 b;
};
template<class T1, class T2>
class test<T1*,T2*>
{
public:
test()
{
cout << "(T1*,T2*)" << endl;
}
private:
T1 a;
T2 b;
};
int main()
{
test<int,int> t1; //調(diào)用基礎的模板
test<int*, int*> t2; //調(diào)用特化的int*版本
return 0;
}
到了這里,關于【高級程序設計語言C++】初識模板的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!