泛型程式設計是獨立于任何特定類型的方式編寫代碼。模闆是泛型程式設計的基礎,模闆使程式員能夠快速建立具有類型安全的類庫集合和函數集合,它的實作,友善了大規模的軟體開發。
模闆提供通用類型和通用函數,定義中包含template,和一對尖括号<>,尖括号裡面是模闆參數。模闆參數與普通參數的差別在于,模闆參數不僅可以傳變量和值,還可以傳類型。模闆參數中定義類型可以使用關鍵字typename或class(效果一樣,有的開發者為區分,函數使用typename,類使用class,實際等同);參數名預設是T,可以為任意字元,效果等同,隻是T較常用,預設。
模闆應放到頭檔案中。模闆本質上就是一種宏定義。
一. 函數模闆
template<typename T>
傳回類型 function(形式參數表)
{
//函數定義體
}
template ---- 聲明建立模闆
typename ---- 表明其後面的符号是一種資料類型,可以用class代替
T ---- 通用資料類型,名稱可以替換,通常為大寫字母
template <class T>
void myswap(T &a, T &b)
{
T temp = a;
a = b;
b = temp;
}
使用函數模闆有兩種方式:自動類型推導、顯示指定類型
void test01()
{
int a = 10, b = 20;
// myswap(a, b);
myswap<int>(a, b);
cout << "a = " << a << endl;
cout << "b = " << b << endl;
模闆的目的是為了提高複用性,将類型參數化。
注:1)自動類型推導,必須推導出一緻的資料類型T才可以使用。
2)模闆必須要确定出T的資料類型,才可以使用。(比如函數沒有參數且不能自動推導出T類型)
template<class T>
void func()
{
cout << "call func" << endl;
}
int main()
{
// func(); // 不能推導出T類型
func<int>();
return 0;
}
普通函數和函數模闆差別:
普通函數調用可以發生自動類型轉換(隐式類型裝換);函數模闆調用時如果利用自動類型推導,不會發生隐式類型轉換;如果利用顯示指定類型的方式,可以發生隐式類型轉換。
建議使用顯示指定類型的方式,調用函數模闆,因為可以自己确定通用類型T。
普通函數與函數模闆的調用規則(函數重載時):
1)如果函數模闆和普通函數都可以實作,優先調用普通函數;
2)可以通過空模闆參數清單來強制調用函數模闆;myPrintf<>(a, b);
3)函數模闆也可以發生重載;
4)如果函數模闆可以産生更好的比對,優先調用函數模闆。
建議在使用模闆時,不要提供普通函數(兩者不要同時出現)。
模闆局限性:自定義類型操作
C++為了解決自定義資料類型的無法正常運作問題,提供模闆的重載,為這些特定的類型提供具體化的模闆。
#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <string>
using namespace std;
class Person
{
public:
Person(string name, int age){
this->m_name = name;
this->m_age = age;
}
string m_name;
int m_age;
};
template <class T>
bool myCompare(T &a, T&b)
{
if(a == b){
return true;
} else {
return false;
}
}
// 利用具體Person的版本實作代碼,具體化優先調用
template<> bool myCompare(Person &p1, Person &p2)
{
if(p1.m_name == p2.m_name && p1.m_age == p2.m_age){
return true;
} else {
return false;
}
}
void test02()
{
Person p1("Tom", 10);
Person p2("Tom", 10);
cout << myCompare(p1, p2) << endl;
}
int main(int argc, char *argv[])
{
test02();
pause();
return 0;
}
利用具體化的模闆可以解決自定義類型的通用化。
學習模闆并不是為了能寫模闆,而是在STL能夠運用系統提供的模闆。
二. 類模闆
template <模闆參數表> class 類名{};
template<class T1, class T2>
class 類{
類成員聲明;
};
T是占位符類型名稱,可以在類被執行個體化的時候進行指定。您可以使用一個逗号分隔的清單來定義多個泛型資料類型。
在類模闆以外定義成員函數
template <模闆參數表> 類型名 類名<參數清單>::函數名(參數表)
模闆類中的函數都是模闆函數。
template <class T> Node<T>::~Node()
{
......
}
參考: