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

下載本文檔

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

文檔簡(jiǎn)介

第六章

模板

6.1模板的概念

C++是強(qiáng)類型語言,因此我們定義求最大值函數(shù)max()時(shí),需要對(duì)不同的數(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ù)只寫出一套代碼?解決問題的一個(gè)方法就是使用模板。所謂模板,就是寫一個(gè)函數(shù)模子,用這個(gè)模子套印出許多功能相同,參數(shù)類型和返回類型不同的函數(shù)。模板是實(shí)現(xiàn)了真正的代碼可重用性??梢赃@么說:函數(shù)重載是指用同一個(gè)名字定義不同的函數(shù),這些函數(shù)功能不同,執(zhí)行不同的操作。函數(shù)模板是指用同一個(gè)名字定義不同的函數(shù),這些函數(shù)功能相同,而參數(shù)類型和返回類型不同。1模板模板分為函數(shù)模板〔模子〕和類模板〔模子〕,允許用戶分別用它們構(gòu)造〔套印〕出〔模板〕函數(shù)和〔模板〕類。圖顯示了模板〔函數(shù)模板和類模板〕,模板函數(shù),模板類和對(duì)象之間的關(guān)系。

模板(函數(shù)模板和類模板)模板函數(shù)模板類對(duì)象實(shí)例化實(shí)例化實(shí)例化模子26.2函數(shù)模板與模板函數(shù)6.2.1函數(shù)模板的聲明與模板函數(shù)的生成函數(shù)模板的聲明格式如下:template<class類型參數(shù)>返回類型函數(shù)名〔模板形參表〕{函數(shù)體}其中template是一個(gè)聲明模板的關(guān)鍵字,它表示聲明一個(gè)模板。例如,將求最大值函數(shù)max()定義成函數(shù)模板,如下所示:template<classT>或template<typenameT>Tmax(Tx,Ty){return(x>y)?x:y;}其中T為類型參數(shù),它可用根本類型或用戶自定義的類型。在使用函數(shù)模板時(shí),必須將其實(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;}程序運(yùn)行結(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為字符型)實(shí)例化5模板函數(shù)max(f1,f2)(f1,f2為浮點(diǎn)型)模板函數(shù)max(d1,d2)(d1,d2為雙精型)模板函數(shù)max(i1,i2)(i1,i2為整型)實(shí)例化實(shí)例化實(shí)例化接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;}程序運(yùn)行結(jié)果為:Thesummaryofintegerarrayare:55Thesummaryofdoublearrayare:59.6幾點(diǎn)說明:⑴在函數(shù)模板中允許使用多個(gè)類型參數(shù)。但在template定義局部的每個(gè)模板形參前必須有關(guān)鍵字class。6幾點(diǎn)說明:例6.3#include<iostream.h>template<classtype1,classtype2>voidmyfunc(type1x,type2y){cout<<x<<’’<<y<<end1;}voidmain(){myfunc(10,”hao”);myfunc(0.123,10L);}程序運(yùn)行結(jié)果為:10hao0.123107⑵在template語句與函數(shù)模板定義語句之間不允許有別的語句。//這是不能編譯的Template<classT>intiI;//錯(cuò)誤,不允許有別的語句Tmax(Tx,Ty){return(x>y)?x:y;}⑶模板函數(shù)類似于重載函數(shù),只不過它更嚴(yán)格一些而已。函數(shù)被重載的時(shí)候,在每個(gè)函數(shù)體內(nèi)可以執(zhí)行不同的動(dòng)作,但同一函數(shù)模板實(shí)例化后的所有模板函數(shù)都必須執(zhí)行相同的動(dòng)作。//不能做函數(shù)模板的voidoutdate(inti){cout<<i;}voidoutdata(doubled){cout<<”d=”<<d<<endl;}86.2.2函數(shù)模板的異常處理雖然函數(shù)模板中的模板形參T可以實(shí)例化為各種類型,但實(shí)例化T的各模板實(shí)參之間必須保持完全一致的類型,否那么會(huì)發(fā)生錯(cuò)誤。請(qǐng)看下面的例子。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);//錯(cuò)誤max(c,i);//錯(cuò)誤}這里出現(xiàn)錯(cuò)誤的原因是,如對(duì)語句max(i,c);編譯器將先按變量i將T解釋為int類型,此后出現(xiàn)的模板實(shí)參c不能解釋為int類型時(shí),便發(fā)生錯(cuò)誤。解決這個(gè)問題有以下兩種方法:⑴采用強(qiáng)制類型轉(zhuǎn)換,如將調(diào)用語句max(i,c);改寫成max(i,int(c));9⑵用非模板函數(shù)重載函數(shù)模板,這種重載有兩種表述方式:①只聲明一個(gè)非模板函數(shù)的原型,而不給出函數(shù)體,它的函數(shù)體是借用函數(shù)模板的函數(shù)體。當(dāng)執(zhí)行此重載版本時(shí)會(huì)自動(dòng)調(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)換}②定義一個(gè)完整的非模板函數(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”);時(shí),執(zhí)行的是這個(gè)重載的非模板函數(shù)。在c++中函數(shù)模板與同名的非模板函數(shù)重載時(shí),調(diào)用的順序遵循下述約定⑴尋找一個(gè)參數(shù)完全匹配的函數(shù),如果找到了就調(diào)用它。⑵尋找一個(gè)函數(shù)模板,將其實(shí)例化,產(chǎn)生一個(gè)匹配的模板函數(shù),假設(shè)找到了,就調(diào)用它。⑶假設(shè)⑴和⑵都失敗,再試一試低一級(jí)的對(duì)函數(shù)的重載方法,假設(shè)找到了,就調(diào)用它。11

6.3類模板和模板類一個(gè)類模板(也稱為類屬類或類生成類)允許用戶為類定義一種模子,使得實(shí)例化類中的某些數(shù)據(jù)成員,某些成員函數(shù)的參數(shù)或者返回值,能取任意數(shù)據(jù)類型。定義一個(gè)類模板,其格式如下:template<classType>class類名{//…};關(guān)鍵字class〔或typename〕后面的Type是類型參數(shù)。在實(shí)例化類定義中,欲采用通用數(shù)據(jù)類型的數(shù)據(jù)成員,成員函數(shù)的參數(shù)或返回值,前面需要加上Type。例如,下面的程序中建立了一個(gè)用來實(shí)現(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];}類模板不代表一個(gè)具體的、實(shí)際的類,而代表一類類。實(shí)際上,類模板的使用就是將類模板實(shí)例化成一個(gè)具體的類,它的格式為:類名<實(shí)際的類型>對(duì)象名;例如,使用上面的類模板,創(chuàng)立兩個(gè)模板參數(shù)為char型的對(duì)象,語句如下:stack<char>s1,s2;14類模板stack(Type)模板類stack(char)模板類stack(int)模板類stack(double)實(shí)例化實(shí)例化實(shí)例化15例6.4類模板stack的例子,在此建立了字符型和整型兩個(gè)堆棧。#include<iostream.h>constintsize=10;template<classType>//聲明一個(gè)類模板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)立兩個(gè)模板參數(shù)為int型的對(duì)象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;}程序運(yùn)行結(jié)果如下:pops1:cpops2:zpopis1:5popis2:6pops1:bpops2:ypopis1:3popis2:4pops1:apops2:xpopis1:1popis2:219例6.5建立一個(gè)單向鏈表類模板,然后建立一個(gè)保存字符的鏈表類。#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();}}程序運(yùn)行結(jié)果如下:abcdefghijklmnopqrstuvwxyz21說明:(1)在每個(gè)類模板定義之前,都需要在前面加上模板聲明template<classType>類模板在使用時(shí),必須在名字后面綴上模板參數(shù)<Type>stack<Type>(2)模板類可以有多個(gè)模板參數(shù),在下面的例中建立了使用兩個(gè)模板參數(shù)的類模板。例6.6使用兩個(gè)模板參數(shù)的類模板#include<iostream.h>template<classT1,classT2>//聲明具有兩個(gè)參數(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();}程序運(yùn)行結(jié)果如下:I=12j=0.15I=xj=Thisisatest236.4應(yīng)用舉例例6.7template<classT>structquenode{Tnodedata;quenode*next;};這里用模板的形式定義了隊(duì)列鏈表的一個(gè)結(jié)點(diǎn)的構(gòu)造,struct也可改為class。也用模板的形式定義了隊(duì)列類,其中4個(gè)數(shù)據(jù)成員,10個(gè)函數(shù)成員:template<classT>classqueue{protected://保護(hù)段①intquesize;//定義隊(duì)列長(zhǎng)度②quenode<T>*head;//定義隊(duì)列列頭③quenode<T>*tail;//定義隊(duì)列列尾④boolallocateerror;

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

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

queue();//構(gòu)造函數(shù)③queue(queue&q){head=NULL;tail=NULL;copy(q);}//構(gòu)造函數(shù),建q隊(duì)列④~queue(){clearque();}//析構(gòu)函數(shù)⑤boolgetallocateerror(){returnallocateerror;}⑥voidpush(T&);//將結(jié)點(diǎn)插入隊(duì)尾⑦boolpop(T&);//從隊(duì)頭取結(jié)點(diǎn)⑧boolisempty(){return(quesize==0)?true:false;}//判斷隊(duì)列是否為空⑨voidclearque();//清空隊(duì)列⑩queue&operator=(queue&q){copy(q);return*this;}//重載賦值運(yùn)算符};其中:黑色的函數(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)

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

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

27

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

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論