c++模板顯示實例化,顯示具體化,隱式實例化

函數模板是C++新增的一種性質,它容許只定義一次函數的實現,便可使用不一樣類型的參數來調用該函數。這樣作能夠減少代碼的書寫的複雜度,同時也便於修改(注:使用模板函數並不會減小最終可執行程序的大小,由於在調用模板函數時,編譯器都根據調用時的參數類型進行了相應實例化)。下面來看看函數模板的使用過程:函數

[cpp] view plain copy.net

  1. struct job  
  2. {  
  3.     char name[20];  
  4.     int salary;  
  5. };  
  6. template <class T> //函數模板聲明,通用變量類型爲T  
  7. void swap(T &a, T &b);  
  8. void showJob(const job &a);//打印job內容  
  9. using std::cin;  
  10. using std::cout;  
  11. using std::endl;  
  12. void main(void)  
  13. {  
  14.     int a = 4;  
  15.     int b = 5;  
  16.     cout<<"Before swap a = "<<a<<" b="<<b<<endl;  
  17.     swap(a, b);  
  18.     cout<<"After swap a = "<<a<<" b="<<b<<endl;    
  19.     job jobA = {"coder", 10000};  
  20.     job jobB = {"manager", 1000};    
  21.     cout<<"Before swap";  
  22.     showJob(jobA);  
  23.     showJob(jobB);  
  24.     cout<<endl;  
  25.     swap(jobA, jobB);  
  26.     cout<<"After swap";  
  27.     showJob(jobA);  
  28.     showJob(jobB);  
  29.     cout<<endl;  
  30. system("pause");  
  31. };   
  32. template<class T> //函數模板實現  
  33. void swap(T &a, T &b)  
  34. {  
  35.     T temp;  
  36.     temp = a;  
  37.     a = b;  
  38.     b = temp;  
  39. }  
  40. void showJob(const job &a)  
  41. {  
  42. cout<<" "<<a.name<<" = "<<a.salary;  
  43. }  


若是在上述job結構互換過程當中只想互換salary,而不換其餘成員變量值那麼怎麼辦呢?C++中能夠經過如下幾種方法來解決這一問題。code

1>顯式具體化
顯式具體化也是基於函數模板的,只不過在函數模板的基礎上,添加一個專門針對特定類型的、實現方式不一樣的具體化函數。blog

[cpp] view plain copyci

  1. template<>void swap<job>(job &a, job &b)  
  2. {  
  3.      int salary;  
  4.      salary = a.salary;  
  5.      a.salary = b.salary;  
  6.      b.salary = salary;  
  7. }  


 

如上所示,該具體化函數的實現與模板並不一致,編譯器解析函數調用時會選擇最匹配的函數定義。get

2>定義同名常規函數編譯器

[cpp] view plain copyit

  1. void swap(job &a, job &b)  
  2. {  
  3.      int salary;  
  4.      salary = a.salary;  
  5.      a.salary = b.salary;  
  6.      b.salary = salary;  
  7. }  


因爲編譯器在重載解析時,會選擇最匹配函數定義,因此在調用swap(jobA, jobB)時,編譯器會選擇void swap(job &a, job &b)函數定義,而屏蔽了模板函數。io

同時,模板函數也能夠重載,其操做與常規函數一致。編譯

[cpp] view plain copy

  1. template <class T> void swap(T &a, T &b);  
  2. template <class T> void swap(T &a, T &b, T &c);  
  3. template <typename T> void swap(T &a, T &b)  
  4. {  
  5.     T temp;  
  6.     temp = a;  
  7.     a = b;  
  8.     b = temp;  
  9. }  
  10. template <typename T> void swap(T &a, T &b, T &c)  
  11. {  
  12.     T temp;  
  13.     temp = a;  
  14.     a = b;  
  15.     b = c;  
  16.     c = temp;  
  17. }  

 

上面主要說的是函數模板的具體化,下面說下模板實例化。

函數模板:

[cpp] view plain copy

  1. #define MAXNAME 128  
  2. struct job  
  3. {  
  4. char name[MAXNAME]:  
  5. int salary;  
  6. };  
  7. template<class T>  
  8. void swap(T &a, T &b )  
  9. {  
  10.   T temp;  
  11.   temp = a;  
  12.   a = b;  
  13.   b = temp;  
  14. };   
  15. template void swap<int>(int &a, int & b);  //顯式實例化,只需聲明  
  16. template<> void swap<job>(job &a, job &b)   //顯式具體化(上面已經講過,注意與實例化區分開,必須有定義)  
  17. {  
  18.   int salary:  
  19.   salary = a.salary:  
  20.   a.salary = b.salary;  
  21.   b.salary = salary;  
  22. };//explicite specialization.  


類模板:

[cpp] view plain copy

  1. template <class T>  
  2. class Arrary  
  3. {  
  4. private:  
  5.   T* ar;  
  6.   int l;  
  7. ...  
  8. };//template class declaration.  
  9. template class Array<int>;   //explicit instantiation. 顯式實例化  
  10. template<> class Array<job>  
  11. {  
  12. private:  
  13.   job* ar;  
  14.   int l;  
  15. };//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型。不然編譯器遇到模板的使用時纔會隱式的生成相應的實例函數。

相關文章
相關標籤/搜索