標籤:

C++類模板詳解

類模板與函數模板的定義和使用類似,我們已經進行了介紹,如果您對函數模板也感興趣,請查看:C++函數模板。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同,如下面語句聲明了一個類:

  1. class Compare_int
  2. {
  3. public :
  4. Compare(int a,int b)
  5. {
  6. x=a;
  7. y=b;
  8. }
  9. int max( )
  10. {
  11. return (x>y)?x:y;
  12. }
  13. int min( )
  14. {
  15. return (x<y)?x:y;
  16. }
  17. private :
  18. int x,y;
  19. };

其作用是對兩個整數作比較,可以通過調用成員函數max和min得到兩個整數中的大者和小者。如果想對兩個浮點數(float型)作比較,需要另外聲明一個類:

  1. class Compare_float
  2. {
  3. public :
  4. Compare(float a,float b)
  5. {
  6. x=a;y=b;
  7. }
  8. float max( )
  9. {
  10. return (x>y)?x:y;
  11. }
  12. float min( )
  13. {
  14. return (x<y)?x:y;
  15. }
  16. private :
  17. float x,y;
  18. }

顯然這基本上是重複性的工作,應該有辦法減少重複的工作。C++在發展的後期增加了模板(template )的功能,提供了解決這類問題的途徑。可以聲明一個通用的類模板,它可以有一個或多個虛擬的類型參數,如對以上兩個類可以綜合寫出以下的類模板:

複製純文本新窗口

  1. template <class numtype> //聲明一個模板,虛擬類型名為numtype
  2. class Compare //類模板名為Compare
  3. {
  4. public :
  5. Compare(numtype a,numtype b)
  6. {
  7. x=a;y=b;
  8. }
  9. numtype max( )
  10. {
  11. return (x>y)?x:y;
  12. }
  13. numtype min( )
  14. {
  15. return (x<y)?x:y;
  16. }
  17. private :
  18. numtype x,y;
  19. };

請將此類模板和前面第一個Compare_int類作一比較,可以看到有兩處不同。1) 聲明類模板時要增加一行 template <class 類型參數名>template意思是「模板」,是聲明類模板時必須寫的關鍵字。在template後面的尖括弧內的內容為模板的參數表列,關鍵字class表示其後面的是類型參數。在本例中numtype就是一個類型參數名。這個名宇是可以任意取的,只要是合法的標識符即可。這裡取numtype只是表示「數據類型」的意思而已。此時,mimtype並不是一個已存在的實際類型名,它只是一個虛擬類型參數名。在以後將被一個實際的類型名取代。2) 原有的類型名int換成虛擬類型參數名numtype。在建立類對象時,如果將實際類型指定為int型,編譯系統就會用int取代所有的numtype,如果指定為float型,就用float取代所有的numtype。這樣就能實現「一類多用」。由於類模板包含類型參數,因此又稱為參數化的類。如果說類是對象的抽象,對象是類的實例,則類模板是類的抽象,類是類模板的實例。利用類模板可以建立含各種數據類型的類。那麼,在聲明了一個類模板後,怎樣使用它呢?怎樣使它變成一個實際的類?先回顧一下用類來定義對象的方法: Compare_int cmp1(4,7); // Compare_int是已聲明的類其作用是建立一個Compare_int類的對象,並將實參4和7分別賦給形參a和b,作為進 行比較的兩個整數。用類模板定義對象的方法與此相似,但是不能直接寫成 Compare cmp(4,7); // Compare是類模板名Compare是類模板名,而不是一個具體的類,類模板體中的類型numtype並不是一個實際的類型,只是一個虛擬的類型,無法用它去定義對象。必須用實際類型名去取代虛擬的類型,具體的做法是: Compare <int> cmp(4,7);即在類模板名之後在尖括弧內指定實際的類型名,在進行編譯時,編譯系統就用int取代類模板中的類型參數numtype,這樣就把類模板具體化了,或者說實例化了。這時Compare<int>就相當於前面介紹的Compare_int類。[例9.14] 聲明一個類模板,利用它分別實現兩個整數、浮點數和字元的比較,求出大數和小數。

#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 > cmp1(3,7); //定義對象cmp1,用於兩個整數的比較 cout<<cmp1.max( )<<" is the Maximum of two integer numbers."<<endl; cout<<cmp1.min( )<<" is the Minimum of two integer numbers."<<endl<<endl; Compare<float > cmp2(45.78,93.6); //定義對象cmp2,用於兩個浮點數的比較 cout<<cmp2.max( )<<" is the Maximum of two float numbers."<<endl; cout<<cmp2.min( )<<" is the Minimum of two float numbers."<<endl<<endl; Compare<char> cmp3(′a′,′A′); //定義對象cmp3,用於兩個字元的比較 cout<<cmp3.max( )<<" is the Maximum of two characters."<<endl; cout<<cmp3.min( )<<" is the Minimum of two characters."<<endl; return 0;}

運行結果如下:7 is the Maximum of two integers.3 is the Minimum of two integers.93.6 is the Maximum of two float numbers.45.78 is the Minimum of two float numbers.a is the Maximum of two characters.A is the Minimum of two characters.還有一個問題要說明: 上面列出的類模板中的成員函數是在類模板內定義的。如果改為在類模板外定義,不能用一般定義類成員函數的形式: 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 >就相當於一個實際的類。大家可以將例9.14改寫為在類模板外定義各成員 函數。歸納以上的介紹,可以這樣聲明和使用類模板: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) 模板可以有層次,一個類模板可以作為基類,派生出派生模板類。有關這方面的知識實際應用較少,本教程暫不作介紹,感興趣的同學可以自行學習。
推薦閱讀:

空白圖文模板
「模板」學習筆記(1)
HTML網頁模板
精美空白日誌模板素材
精美空白模板

TAG:模板 |