函數模板是C++新增的一種性質,它容許只定義一次函數的實現,便可使用不一樣類型的參數來調用該函數。這樣作能夠減少代碼的書寫的複雜度,同時也便於修改(注:使用模板函數並不會減小最終可執行程序的大小,由於在調用模板函數時,編譯器都根據調用時的參數類型進行了相應實例化)。下面來看看函數模板的使用過程:函數
[cpp] view plain copy.net
- struct job
- {
- char name[20];
- int salary;
- };
- template <class T> //函數模板聲明,通用變量類型爲T
- void swap(T &a, T &b);
- void showJob(const job &a);//打印job內容
- using std::cin;
- using std::cout;
- using std::endl;
- void main(void)
- {
- int a = 4;
- int b = 5;
- cout<<"Before swap a = "<<a<<" b="<<b<<endl;
- swap(a, b);
- cout<<"After swap a = "<<a<<" b="<<b<<endl;
- job jobA = {"coder", 10000};
- job jobB = {"manager", 1000};
- cout<<"Before swap";
- showJob(jobA);
- showJob(jobB);
- cout<<endl;
- swap(jobA, jobB);
- cout<<"After swap";
- showJob(jobA);
- showJob(jobB);
- cout<<endl;
- system("pause");
- };
- template<class T> //函數模板實現
- void swap(T &a, T &b)
- {
- T temp;
- temp = a;
- a = b;
- b = temp;
- }
- void showJob(const job &a)
- {
- cout<<" "<<a.name<<" = "<<a.salary;
- }
若是在上述job結構互換過程當中只想互換salary,而不換其餘成員變量值那麼怎麼辦呢?C++中能夠經過如下幾種方法來解決這一問題。code
1>顯式具體化
顯式具體化也是基於函數模板的,只不過在函數模板的基礎上,添加一個專門針對特定類型的、實現方式不一樣的具體化函數。blog
[cpp] view plain copyci
- template<>void swap<job>(job &a, job &b)
- {
- int salary;
- salary = a.salary;
- a.salary = b.salary;
- b.salary = salary;
- }
如上所示,該具體化函數的實現與模板並不一致,編譯器解析函數調用時會選擇最匹配的函數定義。get
2>定義同名常規函數編譯器
[cpp] view plain copyit
- void swap(job &a, job &b)
- {
- int salary;
- salary = a.salary;
- a.salary = b.salary;
- b.salary = salary;
- }
因爲編譯器在重載解析時,會選擇最匹配函數定義,因此在調用swap(jobA, jobB)時,編譯器會選擇void swap(job &a, job &b)函數定義,而屏蔽了模板函數。io
同時,模板函數也能夠重載,其操做與常規函數一致。編譯
[cpp] view plain copy
- template <class T> void swap(T &a, T &b);
- template <class T> void swap(T &a, T &b, T &c);
- template <typename T> void swap(T &a, T &b)
- {
- T temp;
- temp = a;
- a = b;
- b = temp;
- }
- template <typename T> void swap(T &a, T &b, T &c)
- {
- T temp;
- temp = a;
- a = b;
- b = c;
- c = temp;
- }
上面主要說的是函數模板的具體化,下面說下模板實例化。
函數模板:
[cpp] view plain copy
- #define MAXNAME 128
- struct job
- {
- char name[MAXNAME]:
- int salary;
- };
- template<class T>
- void swap(T &a, T &b )
- {
- T temp;
- temp = a;
- a = b;
- b = temp;
- };
- template void swap<int>(int &a, int & b); //顯式實例化,只需聲明
- template<> void swap<job>(job &a, job &b) //顯式具體化(上面已經講過,注意與實例化區分開,必須有定義)
- {
- int salary:
- salary = a.salary:
- a.salary = b.salary;
- b.salary = salary;
- };//explicite specialization.
類模板:
[cpp] view plain copy
- template <class T>
- class Arrary
- {
- private:
- T* ar;
- int l;
- ...
- };//template class declaration.
- template class Array<int>; //explicit instantiation. 顯式實例化
- template<> class Array<job>
- {
- private:
- job* ar;
- int l;
- };//expicit specialization. 顯式具體化,類定義體能夠不一樣於類模板Array
相應的,隱式實例化指的是:在使用模板以前,編譯器不生成模板的聲明和定義實例。只有當使用模板時,編譯器才根據模板定義生成相應類型的實例。如:
int i=0, j=1;
swap(i, j); //編譯器根據參數i,j的類型隱式地生成swap<int>(int &a, int &b)的函數定義。
Array<int> arVal;//編譯器根據類型參數隱式地生成Array<int>類聲明和類函數定義。
顯式實例化:
當顯式實例化模板時,在使用模板以前,編譯器根據顯式實例化指定的類型生成模板實例。如前面顯示實例化(explicit instantiation)模板函數和模板類。其格式爲:
template typename function<typename>(argulist);
template class classname<typename>;
顯式實例化只需聲明,不須要從新定義。編譯器根據模板實現實例聲明和實例定義。
顯示具體化:
對於某些特殊類型,可能不適合模板實現,須要從新定義實現,此時可使用顯示具體化(explicite specialization)。顯示實例化需從新定義。格式爲:
template<> typename function<typename>(argu_list){...};
template<> class classname<typename>{...};
綜上:
template<> void swap<job>(job &a, job &b) {……};是函數模板的顯式具體化,意思是job類型不適用於函數模板swap的定義,所以經過這個顯式具體化從新定義;也可簡寫做template<> void swap(job &a, job &b);
template void swap<job>(job &a, job &b);是函數模板的一個顯式實例化,只需聲明,編譯器遇到這種顯式實例化,會根據原模板的定義及該聲明直接生成一個實例函數,該函數僅接受job型。不然編譯器遇到模板的使用時纔會隱式的生成相應的實例函數。