1. 程式人生 > 實用技巧 >c++ 函式模板

c++ 函式模板

c++的函式模板提供了一種泛型的方法去實現某些設計,模板顧名思義,只是提供一種實現的模板,函式模板不是實際的函式,而是編譯器用於生成一個或多個函式的 "模具"。在編寫函式模板時,不必為形參、返回值或區域性變數指定實際型別,而是使用型別形參來指定通用資料型別。當編譯器遇到對函式的呼叫時,它將檢查其實參的資料型別,並生成將與這些資料型別配合使用的函式程式碼。

  • 函式模板的定義
//形如template <class T,class T1,...>返回值 函式名(引數1,引數2,...)
//eg
template <class T,class T1,...>
T my_fun(T a,T1 b,..)
{

}

通過函式模板,可以看到形參的型別不是確定的,<>中的class表示其後的引數可以是任意型別。 模板引數常稱為型別引數或類屬引數,在模板例項化(即呼叫模板函式時)時需要傳遞的實參是一種資料型別,如int或double之類。不要把這裡的class與類的宣告關鍵字class混淆在一起,雖然它們由相同的字母組成,但含義是不同的。這裡的class表示T是一個型別引數,可以是任何資料型別,如int、float、char等,或者使用者定義的struct、enum或class等自定義資料型別。為了區別類與模板引數中的型別關鍵字class,標準C++提出?了用typename作為模板引數的型別關鍵字,同時也支援使用class。

//形如template <typename T,typename T1,...>返回值 函式名(引數表)
//eg
template <typename T,typename T1,...>
T my_fun(T a,T1 b,..)
{

}

* 函式模板的例項化
例項化發生的時機 模板例項化發生在呼叫模板函式時。當編譯器遇到程式中對函式模板的呼叫時,它才會根據呼叫語句中實參的具體型別,確定模板引數的資料型別,並用此型別替換函式模板中的模板引數,生成能夠處理該型別的函式程式碼,即模板函式,當多次發生型別相同的引數呼叫時,只在第1次進行例項化。

例項化的方式,可以隱式的例項化,也可以顯式的例項化
```c
//當編譯器能夠推斷出引數的型別時,可以隱式的例項化,當然也可以顯式
template <typename T> T Max (T, T);
…
int i = Max (1, 2); 
int i = Max <int>(1, 2); 
float f = Max (1.0, 2.0);
char ch = Max (‘a’, ‘A’);
…
//當編譯器不能推斷出,必須顯式的例項化
template <class T> T max (T, T);
…
int i = max (1, ‘2’); 
// error: data type can’t be deduced
int i = max<int> (1, ‘2’);
…
  • 函式模板的特化
    特化的原因 但在某些情況下,模板描述的通用演算法不適合特定的場合(資料型別等) 比如:如max函式
//定義一個Max的模板,例項化如下
char * cp = Max (“abcd”, “1234”);
例項化為:char * Max (char * a, char * b){return a > b ? a : b;}
//但這顯然不是我們想要的,以為字串的比較應該如下
char * max (char * a, char * b)
{	return strcmp(a, b)>0 ? a : b;   }

特化 所謂特化,就是針對模板不能處理的特殊資料型別,編寫與模板同名的特殊函式專門處理這些資料型別。 模板特化的定義形式: template <> 返回型別 函式名<特化的資料型別>(引數表) { …… }

下面是一個特化的例子

template <class T>
T Max(T a,T b) {
    return (a>b)?a:b;
}
//特化
//template <> 返回型別 函式名<特化的資料型別>(引數表) {}
template<>char * Max<char *>(char *a,char *b) {
    return (strcmp(a,b)>=0)?a:b;
}

函式模板是一個模板,可以用來例項化一系列的函式,例項化的函式成為模板函式