C++類模板函數(shù)模板與模板函數(shù)_第1頁
C++類模板函數(shù)模板與模板函數(shù)_第2頁
C++類模板函數(shù)模板與模板函數(shù)_第3頁
C++類模板函數(shù)模板與模板函數(shù)_第4頁
C++類模板函數(shù)模板與模板函數(shù)_第5頁
已閱讀5頁,還剩30頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第六章

模板

6.1模板的概念

C++是強類型語言,因此我們定義求最大值函數(shù)max()時,需要對不同的數(shù)據(jù)類型分別定義不同的版本,例如:intmax(intx,inty){return(x>y)?x:y;}floatmax(floatx,floaty){return(x>y)?x:y;}doublemax(doublex,doubley){return(x>y)?x:y;}這些函數(shù)版本執(zhí)行的功能都是相同的,只是參數(shù)類型和返回類型不同,能否為上述這些函數(shù)只寫出一套代碼?解決問題的一個方法就是使用模板。所謂模板,就是寫一個函數(shù)模子,用這個模子套印出許多功能相同,參數(shù)類型和返回類型不同的函數(shù)。模板是實現(xiàn)了真正的代碼可重用性??梢赃@么說:函數(shù)重載是指用同一個名字定義不同的函數(shù),這些函數(shù)功能不同,執(zhí)行不同的操作。函數(shù)模板是指用同一個名字定義不同的函數(shù),這些函數(shù)功能相同,而參數(shù)類型和返回類型不同。1模板模板分為函數(shù)模板〔模子〕和類模板〔模子〕,允許用戶分別用它們構(gòu)造〔套印〕出〔模板〕函數(shù)和〔模板〕類。圖顯示了模板〔函數(shù)模板和類模板〕,模板函數(shù),模板類和對象之間的關(guān)系。

模板(函數(shù)模板和類模板)模板函數(shù)模板類對象實例化實例化實例化模子26.2函數(shù)模板與模板函數(shù)6.2.1函數(shù)模板的聲明與模板函數(shù)的生成函數(shù)模板的聲明格式如下:template<class類型參數(shù)>返回類型函數(shù)名〔模板形參表〕{函數(shù)體}其中template是一個聲明模板的關(guān)鍵字,它表示聲明一個模板。例如,將求最大值函數(shù)max()定義成函數(shù)模板,如下所示:template<classT>或template<typenameT>Tmax(Tx,Ty){return(x>y)?x:y;}其中T為類型參數(shù),它可用根本類型或用戶自定義的類型。在使用函數(shù)模板時,必須將其實例化,即用實際的數(shù)據(jù)類型替代它。3例6.1函數(shù)模板的程序#include<iostream.h>#include<string.h>template<classAT>ATmax(ATx,ATy){return(x>y)?X:y;}voidmain(){intil=10,i2=56;floatfl=12.5,f2=24.5;doubleb1=50.344,d2=4656.346;charc1=’k’,c2=’n’;cout<<”themaxofil,i2is:“<<max(i1,i2)<<endl;cout<<”themaxoffl,f2is:“<<max(f1,f2)<<endl;cout<<”themaxofdl,d2is:“<<max(d1,d2)<<endl;cout<<”themaxofcl,c2is:“<<max(c1,c2)<<endl;}程序運行結(jié)果如下:themaxofil,i2is:56themaxoffl,f2is:24.5themaxofdl,d2is:4656.346themaxofcl,c2is:n4函數(shù)模板和模板函數(shù)的關(guān)系

例6.2與指針有關(guān)的模板#include<iostream.h>template<classT>Tsum(T*array,intsize=0){Ttotal=0;for(inti=0;i<size;i++)total+=array[i];returntotal;};函數(shù)模板max(x,y)模板函數(shù)max(c1,c2)(c1,c2為字符型)實例化5模板函數(shù)max(f1,f2)(f1,f2為浮點型)模板函數(shù)max(d1,d2)(d1,d2為雙精型)模板函數(shù)max(i1,i2)(i1,i2為整型)實例化實例化實例化接1例6.2intint_array[]={1,2,3,4,5,6,7,8,9,10};doubledouble_array[]={1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10};voidmain(){intitotal=sum(int_array,10);doubledtotal=sum(double_array,10);cout<<”Thesummaryofintegerarrayare:”<<itotal<<endl;cout<<”Thesummaryofdoublearrayare:”<<dtotal<<endl;}程序運行結(jié)果為:Thesummaryofintegerarrayare:55Thesummaryofdoublearrayare:59.6幾點說明:⑴在函數(shù)模板中允許使用多個類型參數(shù)。但在template定義局部的每個模板形參前必須有關(guān)鍵字class。6幾點說明:例6.3#include<iostream.h>template<classtype1,classtype2>voidmyfunc(type1x,type2y){cout<<x<<’’<<y<<end1;}voidmain(){myfunc(10,”hao”);myfunc(0.123,10L);}程序運行結(jié)果為:10hao0.123107⑵在template語句與函數(shù)模板定義語句之間不允許有別的語句。//這是不能編譯的Template<classT>intiI;//錯誤,不允許有別的語句Tmax(Tx,Ty){return(x>y)?x:y;}⑶模板函數(shù)類似于重載函數(shù),只不過它更嚴(yán)格一些而已。函數(shù)被重載的時候,在每個函數(shù)體內(nèi)可以執(zhí)行不同的動作,但同一函數(shù)模板實例化后的所有模板函數(shù)都必須執(zhí)行相同的動作。//不能做函數(shù)模板的voidoutdate(inti){cout<<i;}voidoutdata(doubled){cout<<”d=”<<d<<endl;}86.2.2函數(shù)模板的異常處理雖然函數(shù)模板中的模板形參T可以實例化為各種類型,但實例化T的各模板實參之間必須保持完全一致的類型,否那么會發(fā)生錯誤。請看下面的例子。Template<classT>Tmax(Tx,Ty){return(x>y)?x:y;}voidfun(inti,charc){max(i,i);//正確,調(diào)用max(int,int)max(c,c);//正確,調(diào)用max(char,char)max(i,c);//錯誤max(c,i);//錯誤}這里出現(xiàn)錯誤的原因是,如對語句max(i,c);編譯器將先按變量i將T解釋為int類型,此后出現(xiàn)的模板實參c不能解釋為int類型時,便發(fā)生錯誤。解決這個問題有以下兩種方法:⑴采用強制類型轉(zhuǎn)換,如將調(diào)用語句max(i,c);改寫成max(i,int(c));9⑵用非模板函數(shù)重載函數(shù)模板,這種重載有兩種表述方式:①只聲明一個非模板函數(shù)的原型,而不給出函數(shù)體,它的函數(shù)體是借用函數(shù)模板的函數(shù)體。當(dāng)執(zhí)行此重載版本時會自動調(diào)用函數(shù)模板的函數(shù)體。template<classT>Tmax(Tx,Ty){return(x>y)?x:y;}intmax(int,int);//非模板函數(shù)的原型voidfun(inti,charc){max(i,i);//正確,調(diào)用max(int,int)max(c,c);//正確,調(diào)用max(char,char)max(i,c);//正確,調(diào)用max(int,int),它支持?jǐn)?shù)據(jù)間的隱式轉(zhuǎn)換max(c,i);//正確,調(diào)用max(int,int),它支持?jǐn)?shù)據(jù)間的隱式轉(zhuǎn)換}②定義一個完整的非模板函數(shù),此方法定義的重載函數(shù),所帶參數(shù)的類型可以隨意,就像一般的重載函數(shù)一樣定義。例如:char*max(char*x,chen*y){return(strcmp(x,y>0)?x:y;)}10當(dāng)出現(xiàn)調(diào)用語句max(“abcd”,”efgh”);時,執(zhí)行的是這個重載的非模板函數(shù)。在c++中函數(shù)模板與同名的非模板函數(shù)重載時,調(diào)用的順序遵循下述約定⑴尋找一個參數(shù)完全匹配的函數(shù),如果找到了就調(diào)用它。⑵尋找一個函數(shù)模板,將其實例化,產(chǎn)生一個匹配的模板函數(shù),假設(shè)找到了,就調(diào)用它。⑶假設(shè)⑴和⑵都失敗,再試一試低一級的對函數(shù)的重載方法,假設(shè)找到了,就調(diào)用它。11

6.3類模板和模板類一個類模板(也稱為類屬類或類生成類)允許用戶為類定義一種模子,使得實例化類中的某些數(shù)據(jù)成員,某些成員函數(shù)的參數(shù)或者返回值,能取任意數(shù)據(jù)類型。定義一個類模板,其格式如下:template<classType>class類名{//…};關(guān)鍵字class〔或typename〕后面的Type是類型參數(shù)。在實例化類定義中,欲采用通用數(shù)據(jù)類型的數(shù)據(jù)成員,成員函數(shù)的參數(shù)或返回值,前面需要加上Type。例如,下面的程序中建立了一個用來實現(xiàn)堆棧的類模板。12constintsize=10Template<classType>classstack{Typestck[size];Inttos;public:voidinit(){tos=0;}voidpush(Typech);Typepop();};成員函數(shù)push()和pop()在類定義體外定義為template<classType>voidstack<Type>::push(Typeob){if(tos==size){cout<<”stackisfull”;return;}stck[tos]=ob;tos++;}13template<classType>Typestack<Type>::pop(){if(tos==0){cout<,”stackisempty”;return0;}tos--;returnstck[tos];}類模板不代表一個具體的、實際的類,而代表一類類。實際上,類模板的使用就是將類模板實例化成一個具體的類,它的格式為:類名<實際的類型>對象名;例如,使用上面的類模板,創(chuàng)立兩個模板參數(shù)為char型的對象,語句如下:stack<char>s1,s2;14類模板stack(Type)模板類stack(char)模板類stack(int)模板類stack(double)實例化實例化實例化15例6.4類模板stack的例子,在此建立了字符型和整型兩個堆棧。#include<iostream.h>constintsize=10;template<classType>//聲明一個類模板classstack{//定義類模板Typestck[size];//數(shù)組可取任意類型,即模板參數(shù)類型TypeInttos;public:voidinit(){tos=0;}voidpush(Typech);//參數(shù)取Type類型Typepop();//返回類型取Type類型};16template<classType>voidstack<Type>::push(Typeob){if(tos==size){cout<<”stackisfull”;return;}stck[tos]=ob;tos++;}template<classType>Typestack<Type>::pop(){if(tos==0){cout<<”stackisempty”;return0;}tos--;returnstck[tos];}17接1例6.4voidmain(){//定義字符堆棧stack<char>s1,s2;inti;s1.init();s2.init();s1.push(‘a(chǎn)’);s2.push(‘x’);s1.push(‘b’);s2.push(‘y’);s1.push(‘c’);s2.push(‘z’);for(i=0;i<3;i++)cout<<”pops1:”<<s1.pop()<<endl;for(i=0;i<3;i++)cout<<”pops2:”<<s2.pop()<<endl;

18//定義整型堆棧stack<int>is1,is2;//創(chuàng)立兩個模板參數(shù)為int型的對象is1.init();is2.init();is1.push(1);is2.push(2);is1.push(3);is2.push(4);is1.push(5);is2.push(6);for(i=0;i<3;i++)cout<<”popis1:”<<is1.pop()<<endl;for(i=0;i<3;i++)cout<<”popis2:”<<is2.pop()<<endl;}程序運行結(jié)果如下:pops1:cpops2:zpopis1:5popis2:6pops1:bpops2:ypopis1:3popis2:4pops1:apops2:xpopis1:1popis2:219例6.5建立一個單向鏈表類模板,然后建立一個保存字符的鏈表類。#include<iostream.h>template<classdata_t>classlist{data_tdata;list*next;public:list(data_td);voidadd(list*node){node->next=this;next=0;}list*getnext(){returnnext;}data_tgetdata(){returndata;}};template<classdata_t>list<data_t>::list(data_td){data=d;next=0;}20voidmain(){list<char>start(‘a(chǎn)’);list<char>*p,*last;inti;//buildalistlast=&start;for(i=1;i<26;i++){p=newlist<char>(‘a(chǎn)’+i);p->add(last);last=p;}cout<<endl;//followthelistp=&start;while(p){cout<<p->getdata();p=p->getnext();}}程序運行結(jié)果如下:abcdefghijklmnopqrstuvwxyz21說明:(1)在每個類模板定義之前,都需要在前面加上模板聲明template<classType>類模板在使用時,必須在名字后面綴上模板參數(shù)<Type>stack<Type>(2)模板類可以有多個模板參數(shù),在下面的例中建立了使用兩個模板參數(shù)的類模板。例6.6使用兩個模板參數(shù)的類模板#include<iostream.h>template<classT1,classT2>//聲明具有兩個參數(shù)的模板classmyclass{//定義類模板T1i;T2j;public:myclass(T1a,T2b){i=a;j=b;}voidshow(){cout<<”I=”<<i<<”j=”<<j<<endl;}};22voidmain(){myclass<int,double>od1(12,0.15);myclass<char,char*>ob2(‘x’,”Thisisatest”);od1.show();ob2.show();}程序運行結(jié)果如下:I=12j=0.15I=xj=Thisisatest236.4應(yīng)用舉例例6.7template<classT>structquenode{Tnodedata;quenode*next;};這里用模板的形式定義了隊列鏈表的一個結(jié)點的構(gòu)造,struct也可改為class。也用模板的形式定義了隊列類,其中4個數(shù)據(jù)成員,10個函數(shù)成員:template<classT>classqueue{protected://保護段①intquesize;//定義隊列長度②quenode<T>*head;//定義隊列列頭③quenode<T>*tail;//定義隊列列尾④boolallocateerror;

24T類型的數(shù)據(jù)quenode類型的指針nodedatanext4個數(shù)據(jù)成員quesizebool類型整數(shù)指向列頭的指針指向列尾的指針headtailallocateerror①

queue©(queue&q);//隊列拷貝函數(shù)public:②

queue();//構(gòu)造函數(shù)③queue(queue&q){head=NULL;tail=NULL;copy(q);}//構(gòu)造函數(shù),建q隊列④~queue(){clearque();}//析構(gòu)函數(shù)⑤boolgetallocateerror(){returnallocateerror;}⑥voidpush(T&);//將結(jié)點插入隊尾⑦boolpop(T&);//從隊頭取結(jié)點⑧boolisempty(){return(quesize==0)?true:false;}//判斷隊列是否為空⑨voidclearque();//清空隊列⑩queue&operator=(queue&q){copy(q);return*this;}//重載賦值運算符};其中:黑色的函數(shù)名③④⑤⑧⑩已在類內(nèi)完成定義,紅色的函數(shù)名①②⑥⑦⑨以模板函數(shù)的形式在下面定義:25②template<classT>queue<T>::queue()//定義構(gòu)造函數(shù){quesize=0;allocateerror=false;head=NULL;tail=NULL;}①template<classT>queue<T>&queue<T>::copy(queue<T>&que)

//將隊列que復(fù)制給當(dāng)前隊列對象{quenode<T>*p,*q,*r;if(head)clearque();quesize=que.quesize;//傳遞隊列長度allocateerror=false;head=NULL;tail=NULL;

26if(!que.head)return*this;//假設(shè)隊列為空,那么返回head=newquenode<T>;//為隊列頭結(jié)點分配存儲空間if(!head)//假設(shè)分配失敗,那么返回{allocateerror=true;return*this;}head->nodedata=que.head->nodedata;//將que隊列頭結(jié)點值賦給當(dāng)前隊列頭結(jié)點head->next=NULL;tail=head;//將隊列尾也指向此結(jié)點r=NULL;p=head;//p指針也指向此結(jié)點q=que.head->next;//q指針指向que隊列的第二個結(jié)點

27

while(q){r=newquenode<T>;//為結(jié)點r分配存儲空間if(!r){allocateerror=true;return*this;}r->nodedata=q->nodedata;r->next=NULL;p->next=r;//將結(jié)點r鏈接到當(dāng)前隊列的鏈上tail=r;//隊尾指針指向r,因為r為最后一個結(jié)點p=p->next;//指針后移q=q->next;}return*this;}28⑥template<classT>voidqueue<T>::push(T&x)//向隊尾插入結(jié)點{quenode<T>*p;p=newquenode<T>;//為p結(jié)點分配存儲空間if(!p)//假設(shè)分配失敗,那么返回{allocateerror=true;return;}p->nodedata=x;if(tail)//假設(shè)隊列非空{(diào)p->next=NULL;tail->next=p;//將p結(jié)點鏈接到尾指針tail后tail=p;//修改隊尾指針}else//假設(shè)隊列為空{(diào)p->next=NULL;tail=p;//p結(jié)點為隊列的頭,又為尾head=p;}quesize++;//長度加1}29⑦template<classT>boolqueue<T>::pop(T&x)//從隊頭取一結(jié)點{quenode<T>*p;if(head)//假設(shè)隊列非空{(diào)x=head->nodedata;//將隊頭的數(shù)據(jù)內(nèi)容賦給xp=head;head=head->next;//修改隊頭指針if(head==NULL)//假設(shè)隊列已刪空,那么tail也改為NULLtail=NULL;deletep;//刪除原頭結(jié)點quesize--;//長度減1returntrue;}returnfalse;}30

⑨t(yī)emplate<classT>voidqueue<T>::clearque()//將隊列清空{(diào)Tp;allocateerror=false;while(pop(p));//循環(huán)提取隊

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論