C++函式模板的具體化和例項化
阿新 • • 發佈:2019-01-05
C++函式模板----模板例項化、具體化
函式模板是C++新增的一種性質,它允許只定義一次函式的實現,即可使用不同型別的引數來呼叫該函式。這樣可以減小程式碼的書寫複雜度,同時也便於修改。
mark:使用函式模板並不會減少最終可執行程式的大小,因為在呼叫模板函式時,編譯器都根據呼叫時的引數型別進行形影的例項化。
函式模板的使用過程:
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;
}
但是存在下列問題,我只想交換結構體中的一個成員變數,應該怎麼處理?有下列幾種方法:
1,顯式具體化
顯式具體化也是基於函式模板的,只不過在函式模板的基礎上,新增一個專門針對特定型別的、實現方式不同的具體化函式。
template<>void swap<job>(job &a, job &b)
{
int salary;
salary = a.salary;
a.salary = b.salary;
b.salary = salary;
}
如上所示,該具體化函式的實現與模板並不一致,編譯器解析函式呼叫時會選擇最匹配的函式定義
2,定義同名常規函式
2>定義同名常規函式
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)函式定義,而遮蔽了模板函式。
同時,模板函式也可以過載,其操作與常規函式一致。
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;
}
上面主要說的是函式模板的具體化,下面說下模板例項化。
函式模板:
#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.
類模板:
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型。否則編譯器遇到模板的使用時才會隱式的生成相應的例項函式。