函數模板爲通用函數的描敘。ios
(1)模板函數不能縮短可執行的程序,仍將使用獨立的函數定義。可是模板函數更加簡單可靠express
(2)能夠重載函數模板,和通常重載同樣,要求函數特徵標(參數表相異),且可以參數表包含非模板參數如int等數組
(3)模板屬於編譯時多態性,由於編譯時自動根據模板生成模板函數。函數重載也是編譯多態性。只有虛函數爲運行多態。less
即提供模板的函數的某些具體化版本,當編譯器找到與函數調用匹配的具體化定義時,將使用該定義而不是模板。例如定義交換函數swap(),交換普通元素和結構體元素,可是要求結構體元素只要求交換部分數據域,以下:函數
struct job{ double salary; int rank; } template<tyname T> void swap(const T&,const T&);//通用版本 template<> void swap<job>(const job&,const job& );//顯式具體化版本 template<tyname T> void swap(const T& a,const T& b)//通用版本 { T temp=a; a=b; b=temp; } template<> void swap<job>(const job& a,const job& b)//顯式具體化版本,並不交換全部部分 { double temp=a.salary; a.salary=b.salary; b.salary=temp; } void main(){ int i=0,j=1; swap(i,j);//(i=1,j=0) ....................... job a={1000.00,1}; job b={2000.00,2} swap(a,b);//(僅僅salary部分交換) ...................... }
(1)徹底匹配,可是匹配優先度:普通函數>顯式具體化函數>模板函數spa
(2)提高轉換匹配(char short轉爲int, long轉爲doubel)指針
(3)標準轉換匹配(int 到 char, long 到double)code
(4)用戶自定義轉換。即下文的顯式實例化。對象
此時應注意,const與非const的區別只存在於指針和引用類型。也就是說,func(int),function(const int)具備相同的匹配等級。若func(int)被最優匹配,則後者也是最優匹配,此時會出現二義性。而後,對於最優匹配的參數表含有指針或者參數的狀況,不會出現此種狀況。ci
編譯時,編譯器傾向選擇最具體且須要最少轉換的函數。固然,也能夠經過人爲指定合適的調用,引導編譯器。如:
template<tyname T> T less(const T& a,const T& b);//#1 { return a<b?:a,b; } int less(int a,int b)//#2 { return a<b?:a,b; } main(){ int i=0,j=1; double m=1.0,n=2.0; less(i,j);//#1 less(m,n);//#2 less<>(i,j);//#1,「<>」引導編譯,要求使用模板函數匹配 less<int>(m,n);//#1,顯式實例化,m、n被強制轉換 }
只有運行時,細節才被真正的肯定。可是在這裏,處理的細節不是類型,當要使用基於值的模板時,必須顯式地指定這些值,纔可以對模板進行實例化。。非類型模板參數(Nontype Template Parameters)只能是整數類型, 指針, 引用。整型必須是常量表達式(constant expression), 指針和引用必須指向靜態類型。
例如定義一個大小事先肯定的stack類:
#include<stdexcept> #include<iostream> using namespace std; template<typename T, int MAXSIZE> class Stack{ private: T elems[MAXSIZE]; int numElems; public: Stack(); void push(T const&); void pop(); T top() const; bool empty() const { return numElems == 0; } bool full() const { return numElems == MAXSIZE; } }; template<typename T, int MAXSIZE> Stack<T, MAXSIZE>::Stack():numElems(0) {} template<typename T, int MAXSIZE> void Stack<T, MAXSIZE>::push(T const& elem) { if(numElems == MAXSIZE) { throw out_of_range("Stack<>::push(): stack is full"); } elems[numElems] = elem; ++numElems; } template<typename T, int MAXSIZE> void Stack<T, MAXSIZE>::pop() { if(numElems <= 0) { throw out_of_range("Stack<>::pop(): stack is empty"); } --numElems; } template<typename T, int MAXSIZE> T Stack<T, MAXSIZE>::top() const { if(numElems <= 0) { throw out_of_range("Stack<>::top(): stack is empty"); } return elems[numElems - 1]; }
#include<iostream> #include<vector> #include<deque> #include<stdexcept> #include<string> #include<cstdlib> #include "stack4.h" using namespace std; int main() { try { Stack<int, 20> int20Stack; Stack<int, 40> int40Stack; Stack<string, 40> stringStack; int20Stack.push(7); cout<<int20Stack.top()<<endl; int20Stack.pop(); stringStack.push("hello"); cout<<stringStack.top()<<endl; stringStack.pop(); stringStack.pop(); } catch(exception const& ex) { cerr<<"Exception: "<<ex.what()<<endl; //return EXIT_FAILURE; } cin.get(); return 0; }
例如求數組大小模板函數:
template<unsigned int N,typename T> int coute(T (&a)[N]){ return sizeof(a)/sizeof(a[0]); }
(1)只能是int,指針或者引用,不能是float或者double,或者類對象之類。例如:
template<double VAT> double process(double v) //error { return V * VAT; } template<string name> //error class MyClass { ... };
(2)使用全局指針做爲模板參數,即extern類型的常量類型:
① 若是在全局域中聲明瞭與模板參數同名的對象函數或類型,則被隱藏。在下面的例子中tmp 的類型不是double 是模板參數Type。
typedef double Type; template <class Type> Type min( Type a, Type b ) { // tmp 類型爲模板參數 Type,不是全局 double Type tmp = a < b ? a : b; return tmp; }
② 在函數模板定義中聲明的對象或類型,不能與模板參數同名。
template <class Type> Type min( Type a, Type b ) { typedef double Type; // 錯誤: 從新聲明模板參數 Type Type tmp = a < b ? a : b; return tmp; }
③ 返回類型也但是模板類型參數
template <class T1, class T2, class T3> T1 min( T2, T3 );
④同一模板參數表必須使用不同的參數名,可是相異的模板參數表可使用相同的參數名
// 錯誤: 模板參數名 Type 的非法重複使用 template <class Type, class Type> Type min( Type, Type ); //正確: 名字 Type 在不一樣模板之間重複使用 template <class Type> Type min( Type, Type ); template <class Type> Type max( Type, Type );
⑤函數模板也能夠被聲明爲inline 或extern 應該把指示符放在模板參數表後面而不是在關鍵字template 前面。
template <typename Type> inline Type min( Type, Type );