1、模板python
template<模板參數表> class 類名 { //類定義體 };//注意分號不可少 templete<模板參數表>返回類型 類名<模板參數名錶>:: 成員函數名1(形參表) { ......;//成員函數定義體 }
模板參數表有兩種:模板類型參數和非模板類型參數。算法
2、函數模板---template關鍵字用於聲明開始進行泛型編程-----typename關鍵字用於聲明泛指類型----函數模板能夠自動推導類型進行調用,也能夠顯示指定具體類型進行調用。編程
一、普通函數模板:數據結構
1 template<typename T> 2 int compare(const T& left,const T& right) 3 { 4 if(left<rigth) 5 {return -1;} 6 if(right<left) 7 {return 1;}
reurn 0; 8 } 9 10 compare<int>(1,2);//使用模板函數
二、類的成員函數模板函數
不只普通函數能夠定義爲模板,類的成員函數也能夠定義爲模板spa
class printer { public: template<typename T> void print(const T& t) { cout<<t<<endl; } } printer p; p.print<const char*>("seu");//打印seu
爲了使用方便,除了直接爲函數模板指定類型參數外,還可讓編譯器從傳遞給函數的實參推斷參數類型,這一功能被稱爲模板實參推斷。指針
1 compare(1,2);//推斷T的類型爲int 2 compare(1.0,2.0);//推斷T的類型爲double 3 p.print("absdsaf");//推斷T的類型爲const char * 4 5 int (*pf)(const int&,const int&)=compare;//推斷T的類型爲int; 6 //經過把函數模板賦值給一個指定類型的函數指針,讓編譯器根據這個指針的類型,對模板實參進行判斷
三、函數模板的重載code
函數模板之間,函數模板與普通函數之間能夠重載。編譯器會根據調用時提供的函數參數,調用可以處理這一類型的最特殊的版本。在特殊性上,通常遵循以下順序:orm
1 template<typename T> 2 void func(T& t) { //通用模板函數 3 cout << "In generic version template " << t << endl; 4 } 5 6 template<typename T> 7 void func(T* t) { //指針版本 8 cout << "In pointer version template "<< *t << endl; 9 } 10 11 void func(string* s) { //普通函數 12 cout << "In normal function " << *s << endl; 13 } 14 15 int i = 10; 16 func(i); //調用通用版本,其餘函數或者沒法實例化或者不匹配 17 func(&i); //調用指針版本,通用版本雖然也能夠用,可是編譯器選擇最特殊的版本 18 string s = "abc"; 19 func(&s); //調用普通函數,通用版本和特殊版本雖然也均可以用,可是編譯器選擇最特化的版本 20 func<>(&s); //調用指針版本,經過<>告訴編譯器咱們須要用template而不是普通函數
四、模板函數的特化blog
有時候函數模板並不能解決個別類型的問題,咱們必須對此進行定製,這就是函數模板的特化。函數模板的特化必須把全部的模板參數所有指定。
1 template<> 2 void func(int i) { 3 cout << "In special version for int "<< i << endl; 4 } 5 6 int i = 10; 7 func(i); //調用特化版本
3、類模板---
類模板只能顯示指定類型參數,沒法自動推斷參數類型。聲明的泛型類型參數能夠出如今類模板的任意地方。類模板必須在頭文件中實現,不能分開實如今不一樣的文件中。
類模板適合以相同的邏輯處理不一樣數據類型的數據,所以很是適合編寫數據結構相關的代碼。一般用來做爲容器(vector)或行爲(clonable)的封裝。
對於一個類模板printer,只能顯示的指定參數類型進行調用
printer<int> p(1);正確 printer p(1);錯誤