模板函數與函數模板 類模板和模板的說明

來源:互聯網
上載者:User

一,模板的概念。
引入模板的原因:
我們已經學過重載,對重載函數而言,C++的檢查機制能通過函數參數的不同及所屬類的不同。正確的調用重載函數。例如,為求兩個數的最大值,我們定義MAX()函數需要對不同的資料類型分別定義不同重載版本。
Int max(int x,int y);
{return(x>y)?x:y ;
}
float max( float x,float y){
return (x>y)? x:y ;}
double max(double x,double y)
{return (c>y)? x:y ;}
但如果在主函數中,我們分別定義了 char a,b;
在執行max(a,b);時 程式就會出錯,因為我們沒有定義char類型的重載版本。
現在,我們再重新審視上述的max()函數,它們都具有同樣的功能,即求兩個數的最大值,能否唯寫一套代碼解決這個問題呢?這樣就會避免因重載函數定義不全面而帶來的調用錯誤。為解決上述問題C++引入模板機制,模板定義:模板就是實現代碼重用機制的一種工具,它可以實作類別型參數化,即把類型定義為參數,從而實現了真正的代碼可重用性。模板分類:磨板分為函數模板後,當編譯系統發現了一個對應的函數調用事,將根據實參的類型來確認是否匹配函數模板中對應的形參然後產生一個重載函數,稱該重載函數為模板函數。函數模板與模板函數的區別: 二者區別可以類比 類與對象的區別。函數 模板與類相似是模板的定義,而模板函數與對象相似。是函數模板的執行個體,具有程式碼。佔用記憶體空間。同樣,在說明了一個類模板後,也可以建立類模板的執行個體即產生模板類。類模板與模板類的區別是:類模板是模板的定義,不是一個實在的類,模板類才是實實在在的類。
二、函數模板與模板憾事
函數模板的一般生命形式如下:
template<class類型形參表>
傳回型別 函數名(形參表)
{//函數定義體 }
說明: templarte是一個聲明模板的關鍵字,表示聲明一個模板關鍵字class不能省略,如果類型形參多餘一個 ,每個形參前都要加class <類型 形參表>可以包含基礎資料型別 (Elementary Data Type)可以包含類類型.
請看以下程式:
#include<iostream.h>
template<class T> /*函數模板聲明*/
T min(T x , T y)
{if(x<y ) return x;
else return y;}
void main( )
{ int n1=2,n2=10;
double d1=1.5,d2=5.6;
cout<<”較小整數:”<<min(n1,n2)<<endl;//執行個體化 min模板函數比較兩整數
cout<<”較小實數:”<<min(d1,d2)<<endl;// 執行個體化min模板函數比較兩雙精確度數
}
程式運行結果: 較小整數:2
較小實數:1.2
程式分析:main()函數中定義了兩個整型變數n1 , n2 兩個雙精確度類型變數d1 , d2然後調用min( n1, n2); 即執行個體化函數模板T min(T x, T y)其中T為int型,求出n1,n2中的最小值.同理調用min(d1,d2)時,求出d1,d2中的最小值.
可用表示函數模板執行個體化過程
函數模板min(x,y)
模板函數min(n1,n2)int型
模板函數min(d1,d2) double型
若main()函數中加一條cout<<min(n1,d1)<<endl;
程式將會出錯,原因是模板函數T的各參數之間必須保持完全一致的類型,並不具有隱式類型轉換功能.
三,類模板與模板類
1.定義一個類模板:
template<class類型形參表>
class類名{
//類定義......
};
 其中,template是聲明各模板的關鍵字,表示聲明一個模板,模板參數可以是一個,也可以是多個,但應是抽象化的結果,不應是具體的(例int,float等)類型,成員函數的參數或傳回型別,前面要加上形參類型.
例如:定義一個類模板:
template<classT1,classT2>
class myclass{T1 I;//
T2 j;//
Public:
Myclass(T1 a,T2 b)//
{I=a; j=b;}
void show( )
{cout<<”I=”<<”j=”<<j<<endl;}};
在主函數中若定義了一模板類 myclass<int,double>並且聲明一個類對象ob1(1  引用語句:myclass<int,double >ob(2,0.1);注意:myclass<int,double>執行個體化了類模板,即將T1執行個體為int 類型,T2為double 類型,這樣我們就得到了一個模板類.然後就可以定義類對象ob1並初始化.
還可以定義另一個模板類如: myclass<double ,char>
可通過表示類模板與模板類的關係
類模板myclass<T!,T2>
模板類myclass(int,double)
模板類nyclass<double,char>
總結:函數模板是一類函數的抽象,代表了一類函數,這一類函數具有相同的功能,代表一 具體的函數,能被類對象調用,而函數模板絕不能被類對象調用.
類模板是對類的抽象,代表一類類,這些類具有相同的功能,但資料成員類型及成員函數傳回型別和形參類型不同.模板類是類模板類的執行個體.代表一具體的類,可以定義類對象 ,而不能給類模板定義對象.
 

 

 

 

 

 

 

 

 

-------------------------------

名正言順  
  中國有句古話:名不正則言不順。一樣東西,名字如果用的不好,不但聽起來不舒服,而且真實的本質也容易被掩蓋。如果一樣東西有一個好名字,我們就能更容易的記住它和理解它。  
   
  在現代漢語中,許多詞的重點都在後面,比如下面我們經常看到的兩個詞語。  
   
  冰雪聰明。  
   
  聰明冰雪。  
   
  冰雪聰明強調的是聰明,她像冰雪一樣的聰明。  
   
  聰明冰雪強調的是冰雪,她很聰明,看上去更是冰雪般的玲瓏剔透純潔。  
   
  在C++中有好幾個這樣的術語,但是我們很多時候用的並不正確,幾乎是互相替換混淆使用。下面我想徹底辨清幾個術語,這樣就可以避免很多概念上的混淆和使用上的錯誤。  
   
  這幾個詞是:  
   
  函數指標——指標函數  
   
  數組指標——指標數組  
   
  類模板——模板類  
   
  函數模板——模板函數  
   
  最終在使用中,我們就可以讓它們實至名歸,名正言順。  
   
     
   
  1.函數指標——指標函數  
   
  函數指標的重點是指標。表示的是一個指標,它指向的是一個函數,例子:  
   
  int   (*pf)();  
   
  指標函數的重點是函數。表示的是一個函數,它的傳回值是指標。例子:  
   
  int*   fun();  
   
     
   
  2.數組指標——指標數組  
   
  數組指標的重點是指標。表示的是一個指標,它指向的是一個數組,例子:  
   
  int   (*pa)[8];  
   
  指標數組的重點是數組。表示的是一個數組,它包含的元素是指標。例子;  
   
  int*   ap[8];  
   
     
   
  3.類模板——模板類(class   template——template   class)  
   
  類模板的重點是模板。表示的是一個模板,專門用於產生類的模子。例子:  
   
  template   <typename   T>  
   
  class   Vector  
   
  {  
   
              …  
   
  };  
   
  使用這個Vector模板就可以產生很多的class(類),Vector<int>、Vector<char>、Vector<   Vector<int>   >、Vector<Shape*>……。  
   
  模板類的重點是類。表示的是由一個模板產生而來的類。例子:  
   
  上面的Vector<int>、Vector<char>、……全是模板類。  
   
  這兩個詞很容易混淆,我看到很多文章都將其用錯,甚至一些英文文章也是這樣。將他們區分開是很重要的,你也就可以理解為什麼在定義模板的標頭檔.h時,模板的成員函數實現也必須寫在標頭檔.h中,而不能像普通的類(class)那樣,class的聲明(declaration)寫在.h檔案中,class的定義(definition)寫在.cpp檔案中。請參照Marshall   Cline的《C++   FAQ   Lite》中的[34]   Container   classes   and   templates中的[34.12]   Why   can't   I   separate   the   definition   of   my   templates   class   from   it's   declaration   and   put   it   inside   a   .cpp   file?   URL地址是http://www.parashift.com/c++-faq-lite/containers-and-templates.html#faq-34.12  
   
  我將幾句關鍵的段落摘錄如下,英文很好理解:  
   
  In   order   for   the   compiler   to   generate   the   code,   it   must   see   both   the   template   definition   (not   just   declaration)   and   the   specific   types/whatever   used   to   "fill   in"   the   template.   For   example,   if   you're   trying   to   use   a   Foo<int>,   the   compiler   must   see   both   the   Foo   template   and   the   fact   that   you're   trying   to   make   a   specific   Foo<int>.    
   
  Suppose   you   have   a   template   Foo   defined   like   this:    
   
    template<class   T>  
    class   Foo   {  
    public:  
        Foo();  
        void   someMethod(T   x);  
    private:  
        T   x;  
    };    
   
  Along   with   similar   definitions   for   the   member   functions:    
   
    template<class   T>  
    Foo<T>::Foo()  
    {  
        ...  
    }  
     
    template<class   T>  
    void   Foo<T>::someMethod(T   x)  
    {  
        ...  
    }    
   
  Now   suppose   you   have   some   code   in   file   Bar.cpp   that   uses   Foo<int>:    
   
    //   Bar.cpp  
     
    void   blah_blah_blah()  
    {  
        ...  
        Foo<int>   f;  
        f.someMethod(5);  
        ...  
    }    
   
  Clearly   somebody   somewhere   is   going   to   have   to   use   the   "pattern"   for   the   constructor   definition   and   for   the   someMethod()   definition   and   instantiate   those   when   T   is   actually   int.   But   if   you   had   put   the   definition   of   the   constructor   and   someMethod()   into   file   Foo.cpp,   the   compiler   would   see   the   template   code   when   it   compiled   Foo.cpp   and   it   would   see   Foo<int>   when   it   compiled   Bar.cpp,   but   there   would   never   be   a   time   when   it   saw   both   the   template   code   and   Foo<int>.   So   by   rule   above,   it   could   never   generate   the   code   for   Foo<int>::someMethod().    
   
  關於一個預設模板參數的例子:  
   
  template   <typename   T   =   int>  
   
  class   Array  
   
  {  
   
              …  
   
  };  
   
  第一次我定義這個模板並使用它的時候,是這樣用的:  
   
  Array   books;//我認為有預設模板參數,這就相當於Array<int>   books  
   
  上面的用法是錯誤的,編譯不會通過,原因是Array不是一個類。正確的用法是Array<>   books;  
   
  這裡Array<>就是一個用於預設模板參數的類模板所產生的一個具體類。  
   
     
   
  4.函數模板——模板函數(function   template——template   function)  
   
  函數模板的重點是模板。表示的是一個模板,專門用來生產函數。例子:  
   
  template   <typename   T>  
   
  void   fun(T   a)  
   
  {  
   
              …  
   
  }  
   
  在運用的時候,可以顯式(explicitly)生產模板函數,fun<int>、fun<double>、fun<Shape*>……。  
   
  也可以在使用的過程中由編譯器進行模板參數推導,幫你隱式(implicitly)產生。  
   
  fun(6);//隱式產生fun<int>  
   
  fun(8.9);//隱式產生fun<double>  
   
  fun(‘a’);//   隱式產生fun<char>  
   
  Shape*   ps   =   new   Cirlcle;  
   
  fun(ps);//隱式產生fun<Shape*>  
   
     
   
  模板函數的重點是函數。表示的是由一個模板產生而來的函數。例子:  
   
  上面顯式(explicitly)或者隱式(implicitly)產生的fun<int>、fun<Shape*>……都是模板函數。  
   
  關於模板本身,是一個非常龐大的主題,要把它講清楚,需要的不是一篇文章,而是一本書,幸運的是,這本書已經有了:David   Vandevoorde,   Nicolai   M.   Josuttis寫的《C++   Templates:   The   Complete   Guide》。可惜在大陸買不到紙版,不過有一個電子版在網上流傳。  
   
     
   
  模板本身的使用是很受限制的,一般來說,它們就只是一個產生類和函數的模子。除此之外,運用的領域非常少了,所以不可能有什麼模板指標存在的,即指向模板的指標,這是因為在C++中,模板就是一個代碼的代碼生產工具,在最終的代碼中,根本就沒有模板本身存在,只有模板具現出來的具體類和具體函數的代碼存在。  
   
  但是類模板(class   template)還可以作為模板的模板參數(template   template   parameter)使用,在Andrei   Alexandrescu的《Modern   C++   Design》中的基於策略的設計(Policy   based   Design)中大量的用到。  
   
  template<   typename   T,   template<typename   U>   class   Y>  
   
  class   Foo  
   
  {  
   
              …  
   
  };  
   
     
   
  從文章的討論中,可以看到,名字是非常重要的,如果對名字的使用不恰當的話,會引起很多的麻煩和誤解。我們在實際的程式中各種標識符的命名也是一門學問,為了清晰易懂,有時候還是需要付出一定的代價。  
   
  最後提醒:在本文的幾個術語中,語言的重心在後面,前面的詞是作為形容詞使用的。  
   
  吳桐寫於2003.6.1  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.