模板與泛型程式設計(二)--《C++ primer》
通常在呼叫普通函式時,我們只要做到將函式的宣告放到其定義的前面,保證編譯器先掌握到函式的宣告,因此我們會把其函式宣告放到標頭檔案,而其定義放到原始檔當中;但是模板不同,為了生成一個例項化版本,編譯器需要掌握函式模板或類模板成員函式的定義,所以模板標頭檔案通常既包括宣告又包含定義。原因在於模板編譯的一個特性:模板編譯中,當編譯器遇到一個模板定義時,它並不生成程式碼。只有當我們例項化出模板的一個特定版本時,編譯器才會生成程式碼。
下面介紹:類模板
首先什麼是類模板?
其實類模板是類的一個定義,可以用來定義一組特定型別的類。類模板用template關鍵字後接用尖括號(<>)括住、以逗號分隔的一個或多個模板形參的列表來定義。類模板針對僅資料成員和成員函式型別不同的類。
類模板的作用?
百度百科的定義是:模板是泛型程式設計的基礎,所謂泛型程式設計就是用獨立於任何特定型別的方式編寫程式碼,所以簡單地說,類是物件的抽象,而模板又是類的抽象,也就用模板能定義出具體類,再理解深刻點:在c++裡,常說的多型一般分為兩種:一種是執行時的多型,也就是虛擬函式體現的多型,另一種是編譯時的多型,也就是泛型程式設計的多型,體現在引數的多型在作用上是為了提高程式設計效率。定義:
template <class T,class T,。。。>
返回型別 函式名(引數列表){
函式體
}
上面class關鍵字可以用typename關鍵字代替,效果是一樣的。還有模板形參不能為空,一旦聲明瞭類模板就可以用類模板的形參名宣告類中的成員變數和成員函式,即可以在類中使用內建型別的地方都可以使用模板形參名來宣告,如
template <class T>
class Stu{
public: T x;
T y;
T Scores(T a, T &b);
};
在類Stu中聲明瞭兩個型別為T的成員變數x和y,還聲明瞭一個返回型別為T的帶兩個引數型別為T的函式Scores。
成員函式的例項化和注意項
#include <iostream> using namespace std; template <class numtype> class Compare{ public : Compare(numtype a,numtype b){ x=a;y=b; } numtype max(){ return (x>y)?x:y; } numtype min( ){ return (x<y)?x:y; } private : numtype x,y; }; int main( ) { Compare<int > compare1(8,9); cout<<compare1.max( )<<" 是最大值"<<endl; cout<<compare1.min( )<<" 是最小值"<<endl<<endl; Compare<float > compare2(36.6,12.82); cout<<compare2.max( )<<" 是最大值"<<endl; cout<<compare2.min( )<<" 是最小值"<<endl<<endl; Compare<char> compare3('d','M'); cout<<compare3.max( )<<" 是最大值"<<endl; cout<<compare3.min( )<<" 是最小值"<<endl; return 0; }
以上是宣告一個類模板,利用它分別實現兩個整數、浮點數和字元的比較,求出最大數和最小數。
上面列出的類模板中的成員函式是在類模板內定義的;如果改為在類模板外定義,不能用一般定義類成員函式的形式:numtype Compare::max( ) {.....} 而應當寫成類模板的形式:
template <class numtype>
Compare<numtype> Compare<numtype>::max(){
return (x>y)?x:y;
}
因為我們在類模板外定義其成員時,我們並不在類的作用域中,直接遇到類名才表示進入類的作用域。上面template <class numtype>表示是類模板,後面的Compare <numtype>是一個整體,是帶參的類。表示所定義的max函式是在類Compare <numtype>的作用域內的。在定義物件時,使用者當然要指定具體的型別,進行編譯時就會將類模板中的虛擬型別名numtype全部用實際的型別代替。