一個簡單的例子 兩個數比大小
class Compare_int
{
public :Compare(int a,int b){x=a;y=b;}int max( ){return (x>y)?x:y;}int min( ){return (x<y)?x:y;}
private :int x,y;
};
class Compare_float
{
public :Compare(float a,float b){x=a;y=b;}float max( ){return (x>y)?x:y;}float min( ){return (x<y)?x:y;}
private :float x,y;
}
- 僅僅是因為參數的類型不一致,就得重新寫一個函數來比較大小,這個過程是極其繁瑣的,因此引出模板
聲明模板
template <class numtype> //聲明一個模板,虛擬類型名為numtype
class Compare //類模板名為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;
};
與先前不使用模板之間的區別
- 聲明類模板時要增加一行 ? ?template <class 類型參數名> template意思是“模板”,是聲明類模板時必須寫的關鍵字。在template后面的尖括號內的內容為模板的參數表列,關鍵字class表示其后面的是類型參數。在本例中numtype就是一個類型參數名。這個名宇是可以任意取的,只要是合法的標識符即可。這里取numtype只是表示“數據類型”的意思而已。此時,mimtype并不是一個已存在的實際類型名,它只是一個虛擬類型參數名。在main函數使用的時候將被一個實際的類型名取代,比如int、float、double類型
- 原有的類型名int換成虛擬類型參數名numtype。 在建立類對象時,如果將實際類型指定為int型,編譯系統就會用int取代所有的numtype,如果指定為float型,就用float取代所有的numtype。這樣就能實現“一類多用”。
- 由于類模板包含類型參數,因此又稱為參數化的類。如果說類是對象的抽象,對象是類的實例,則類模板是類的抽象,類是類模板的實例。 利用類模板可以建立含各種數據類型的類。
使用
- Compare <int> cmp(4,7); 即在類模板名之后在尖括號內指定實際的類型名,在進行編譯時,編譯系統就用int取代類模板中的類型參數numtype,這樣就把類模板具體化了,或者說實例化了。這時Compare<int>就相當于前面介紹的Compare_int類。
- 然后就可以使用std::cout << cmp.max() <<std::endl; 輸出其內部定義的函數
- [例] 聲明一個類模板,利用它分別實現兩個整數、浮點數和字符的比較,求出大數和小數。
注意事項
- 還有一個問題要說明: 上面列出的類模板中的成員函數是在類模板內定義的。如果改為在類模板外定義,不能用一般定義類成員函數的形式:
- numtype Compare::max( ) {…} //不能這樣定義類模板中的成員函數,而應當寫成類模板的形式:
template <class numtype>numtype Compare<numtype>::max( ){return (x>y)?x:y;}
- 上面第一行表示是類模板,第二行左端的numtype是虛擬類型名,后面的Compare <numtype>是一個整體,是帶參的類。表示所定義的max函數是在類Compare <numtype>的作用域內的。在定義對象時,用戶當然要指定實際的類型(如int),進行編譯時就會將類模板中的虛擬類型名numtype全部用實際的類型代替。這樣Compare <numtype >就相當于一個實際的類。
總結
- 歸納以上的介紹,可以這樣聲明和使用類模板:
1)?先寫出一個實際的類。由于其語義明確,含義清楚,一般不會出錯。
2) 將此類中準備改變的類型名(如int要改變為float或char)改用一個自己指定的虛擬類型名(如上例中的numtype)。
3) 在類聲明前面加入一行,格式為:
? ? template <class 虛擬類型參數>
如:
? ? template <class numtype> //注意本行末尾無分號
? ? class Compare
? ? {…}; //類體
4) 用類模板定義對象時用以下形式:
? ? 類模板名<實際類型名> 對象名;
? ? 類模板名<實際類型名> 對象名(實參表列);
如:
? ? Compare<int> cmp;
? ? Compare<int> cmp(3,7);
5) 如果在類模板外定義成員函數,應寫成類模板形式:
? ?template <class 虛擬類型參數>
? ?函數類型 類模板名<虛擬類型參數>::成員函數名(函數形參表列) {…}
關于類模板的幾點說明:
- 1)?類模板的類型參數可以有一個或多個,每個類型前面都必須加class,如:
- template <class T1,class T2>
- class someclass{…};
- 在定義對象時分別代入實際的類型名,如:someclass<int,double> obj;
- 2) 和使用類一樣,使用類模板時要注意其作用域,只能在其有效作用域內用它定義對象。
- 3) 模板可以有層次,一個類模板可以作為基類,派生出派生模板類。有關這方面的知識實際應用較少,本教程暫不作介紹,感興趣的同學可以自行學習。