面向?qū)ο蟪绦蛟O(shè)計(jì)輔導(dǎo)材料-1_第1頁(yè)
面向?qū)ο蟪绦蛟O(shè)計(jì)輔導(dǎo)材料-1_第2頁(yè)
面向?qū)ο蟪绦蛟O(shè)計(jì)輔導(dǎo)材料-1_第3頁(yè)
面向?qū)ο蟪绦蛟O(shè)計(jì)輔導(dǎo)材料-1_第4頁(yè)
面向?qū)ο蟪绦蛟O(shè)計(jì)輔導(dǎo)材料-1_第5頁(yè)
已閱讀5頁(yè),還剩44頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第12章模板(Template)面向?qū)ο蟪绦蛟O(shè)計(jì)(C++)12.1引言12.1引言:IntStack創(chuàng)建一個(gè)棧,這個(gè)棧類只存放int類型的值1.支持初始化、push()、pop()、清除等方法;2.棧中所有元素的類型都是int.VP用來(lái)存放int的棧類IntStackclassIntStack{int*v;//棧底int*p;//棧頂intsz;//棧的大小public:IntStack(ints){v=p=newint[sz=s];}~IntStack(){delete[]v;}voidpush(inta){*p++=a};intpop(){return*--p;}intsize()const{returnp-v;}};12.2代碼重用12.2如何實(shí)現(xiàn)代碼重用?VPVPCharStackObjStack

現(xiàn)在希望再創(chuàng)建能存放其他類型的棧類,如:char,float,甚至用戶自定義的類型對(duì)象。

從棧的結(jié)構(gòu)和操作方式上來(lái)說(shuō),除了每個(gè)元素的類型不一樣外,其它沒有任何區(qū)別。因此應(yīng)該可以重用IntStack的代碼。問題是:如何重用?12.2.1C的方法之一:代碼拷貝classCharStack{

char*v;//棧底char*p;//棧頂intsz;//棧的大小public:CharStack(ints){v=p=newchar[sz=s];}~CharStack(){delete[]v;}voidpush(chara){*p++=a};

charpop(){return*--p;}intsize()const{returnp-v;}};缺點(diǎn):1.表現(xiàn)繁瑣;2.易發(fā)生錯(cuò)誤;3.缺乏美感;非常低效!12.2.2C的方法之二:typedeftypedefintT;classStack{

T*v;//棧底

T*p;//棧頂intsz;//棧的大小public:Stack(ints){v=p=newT[sz=s];}~Stack(){delete[]v;}voidpush(Ta){*p++=a};

Tpop(){return*--p;}intsize()const{returnp-v;}};缺點(diǎn):1.每次使用Stack之前,都必須加上typedef語(yǔ)句,很麻煩。2.由于T是全局名,無(wú)法重新定義,一個(gè)類不能同時(shí)用到char棧和int棧;12.2.3smalltak方法(略)使用繼承復(fù)雜,混亂!12.2.4C++的方法:模板改進(jìn)typedef,將它從預(yù)處理器移入到編譯器中。新的代碼替換裝置稱為“模板”(template)。非常象宏,卻更清晰,更易于使用;模板實(shí)際上是一組類;形式上很簡(jiǎn)潔。12.3模板語(yǔ)法12.3.1類模板定義template<classT>class類模板名{//類模板的定義};注:T是一個(gè)類模板的類型參數(shù),可以有一個(gè)或多個(gè),可以是任意類型。template<classT>

classStack{

T*v;//棧底

T*p;//棧頂intsz;//棧的大小public:Stack(ints){v=p=newT[sz=s];}~Stack(){delete[]v;}voidpush(Ta){*p++=a};

Tpop(){return*--p;}intsize()const{returnp-v;}};例:Stack<T>12.3.2類模板實(shí)例化給類模板的參數(shù)指定具體的類型,這一過(guò)程稱為

“類模板的實(shí)例化”。類模板名<具體類型表>

Stack<int>;//實(shí)例化成int型棧類;Stack<char>;//實(shí)例化成char型棧類;注意:類模板實(shí)例化后的結(jié)果是類,而不是對(duì)象!12.3.3類對(duì)象生成類模板實(shí)例化得到的類可以進(jìn)行實(shí)例化,生成最終的對(duì)象。Stack<int>si(20);//創(chuàng)建一個(gè)大小為20的整形棧;Stack<char>si(40);//創(chuàng)建一個(gè)字符型棧;Stackstack(100);//error,未指定模板參數(shù),

類模板與類的實(shí)例化Stack<T>Stack<int>Stack<char>…………Stack<int>sint(10)Stack<int>si2(20)……模板實(shí)例化類實(shí)例化完整的stack<T>程序:template<classT>classStack{

T*v;//棧底

T*p;//棧頂intsz;//棧的大小public:Stack(ints){v=p=newT[sz=s];}~Stack(){delete[]v;}voidpush(Ta){*p++=a};

Tpop(){return*--p;}intsize()const{returnp-v;}};voidmain(){inti;Stack<char>sch(20);

Stack<char>sch2(20);

Stack<int>sint(10);for(i=0;i<10;i++){sint.push(i+1);}for(i=0;i<20;i++){sch.push(‘*’);}//….for(i=10;i>0;i--){if(sint.pop()!=i){error();}}for(i=0;i<20;i++){if(sch.pop()!=‘*’){error();}}}一個(gè)值得注意的問題!12.3.4非內(nèi)聯(lián)函數(shù)定義12.3.4.1語(yǔ)法template<classT>返回值類型類模板名<類模板參數(shù)>::成員函數(shù)名(函數(shù)參數(shù)1,函數(shù)參數(shù)2,函數(shù)參數(shù)3)非內(nèi)聯(lián)函數(shù)定義的Stack<T>template<classT>classStack{T*v;//棧底T*p;//棧頂intsz;//棧的大小public:Stack(ints;~Stack();voidpush(Ta);Tpop();intsize();};template<classT>Stack<T>::Stack(ints){v=p=newT[sz=s];}template<classT>Stack<T>::~Stack(){delete[]v;}

template<classT>voidStack<T>::push(Ta){*p++=a};template<classT>TStack<T>::pop(){return*--p;}template<classT>intStack<T>::size()const{returnp-v;}};12.3.4.2關(guān)于頭文件對(duì)類來(lái)說(shuō),在創(chuàng)建非內(nèi)聯(lián)函數(shù)定義時(shí),我們通常把定義放在.h文件中,而把實(shí)現(xiàn)放在.cpp中。

(實(shí)際上是所謂的頭文件原則:“在頭文件中,不要放置分配存儲(chǔ)空間的任何東西”,為了防止在連接期間的多重定義錯(cuò)誤。)對(duì)模板來(lái)說(shuō),即使是在創(chuàng)建非內(nèi)聯(lián)函數(shù)定義時(shí),模板的所有定義和實(shí)現(xiàn)都必須放入一個(gè)頭文件中。

why?

因?yàn)槟0搴芴厥?,在template<…>之后的任何東西都意味著編譯器在當(dāng)時(shí)不為它分配存儲(chǔ)空間(即不編譯成目標(biāo)代碼),而是一直處于等待狀態(tài)直到一個(gè)模板示例被告知。如果沒有被實(shí)例化,模板不會(huì)被編譯成目標(biāo)代碼:template<classT>classStack{

T*v;//棧底

T*p;//棧頂intsz;//棧的大小public:Stack(ints;~Stack();voidpush(Ta);

Tpop();intsize();};文件:Stack.htemplate<classT>Stack<T>::Stack(ints){v=p=newT[sz=s];}template<classT>Stack<T>::~Stack(){delete[]v;}template<classT>voidStack<T>::push(Ta){*p++=a};

template<classT>

TStack<T>::pop(){return*--p;}

template<classT>intStack<T>::size()const{returnp-v;}};文件:Stack.cpp#include“Stack.h”voidmain(){Stack<int>si(10);si.push(1);//連接錯(cuò)誤}文件:test.cpperrorLNK2001:unresolvedexternalsymbol"public:int__thiscallStack<int>::push(int)"(?push@?$stack@H@@QAEHXZ)發(fā)生連接錯(cuò)誤:FromMSDN:LinkerToolsErrorLNK2001unresolvedexternalsymbol"symbol"Codewillgeneratethiserrormessageifitreferencessomething(likeafunction,variable,orlabel)thatthelinkercan’tfindinallthelibrariesandobjectfilesitsearches.Ingeneral,therearetworeasonsthiserroroccurs:whatthecodeasksfordoesn’texist(thesymbolisspelledincorrectlyorusesthewrongcase,forexample),orthecodeasksforthewrongthing(youareusingmixedversionsofthelibraries?somefromoneversionoftheproduct,othersfromanotherversion).NumerouskindsofcodingandbuilderrorscancauseLNK2001.Severalspecificcausesarelistedbelow,andsomehavelinkstomoredetailedexplanations.……12.3.5模板中的常量模板參數(shù)并不局限于類定義的類型,可以使用編譯器內(nèi)置類型。

tempate<classT,intsize=100>classArray{…;}類型參數(shù)內(nèi)置類型參數(shù)參數(shù)的默認(rèn)值例:模板中的常量#include"../require.h"#include<iostream>usingnamespacestd;template<classT,intsize=100>classArray{Tarray[size];//在實(shí)例化時(shí),設(shè)置Array類的長(zhǎng)度public:T&operator[](intindex){//重載[]實(shí)現(xiàn)關(guān)聯(lián)數(shù)組

require(index>=0&&index<size,"Indexoutofrange");returnarray[index];}intlength()const{returnsize;}};classNumber{floatf;public:Number(floatff=0.0f):f(ff){}Number&operator=(constNumber&n){//重載賦值符f=n.f;return*this;}operatorfloat()const{returnf;}

friendostream&operator<<(ostream&os,constNumber&x){returnos<<x.f;}};template<classT,intsize=20>classHolder{Array<T,size>*np;public:Holder():np(0){}T&operator[](inti){require(0<=i&&i<size);if(!np)np=newArray<T,size>;returnnp->operator[](i);}intlength()const{returnsize;}~Holder(){deletenp;}};intmain(){Holder<Number>h;

for(inti=0;i<20;i++)h[i]=i;

for(intj=0;j<20;j++)cout<<h[j]<<endl;}///:~12.4模板的派生12.4.1從類派生模板模板實(shí)際上是一組類,如果某一類定義了這一組類的公共屬性,則模板可以從該類派生。classBase{inti;protected:floatf;public:voidg(){cout<<“g”<endl;}};template<classT>classderived:publicBase{Tt;//…};voidmain(){derived<int>di;derived<char>dc;di.g();//dc.g();}12.4.2從類模板派生模板template<classT>classBase{inti;protected:Tf;public:voidg(){cout<<“g”<endl;}};類模板的基類如果也是模板,派生類模板的參數(shù)表應(yīng)包含基類模板的參數(shù)。template<classT1,classT2>classderived:publicBase<T2>{T1t;//…};voidmain(){derived<int,char>di;derived<char,float>dc;di.g();//dc.g();}12.4.2從類模板派生模板(續(xù))如果派生類沒有類型參數(shù),或者說(shuō)它的類型參數(shù)與基類的類型參數(shù)相同時(shí),派生類地模板參數(shù)只要包含基類的模板參數(shù)就可以了template<classT>classC:publicBase<T>//模板C的參數(shù)與基類相同{Tc;//…};12.5函數(shù)模板實(shí)際上是定義了一組函數(shù)12.5.1函數(shù)模板的定義template<模板參數(shù)表>返回值類型函數(shù)名(函數(shù)參數(shù)表){//函數(shù)模板的定義}例1:求兩個(gè)對(duì)象間的最大值template<classT>Tmax(Ta,Tb){returna>b?a:b;}這里T可以是int,char,float,或者任何重載了>算符的對(duì)象。例2:關(guān)于模板參數(shù)template<classT>voidf(){//error,函數(shù)參數(shù)列表中無(wú)函數(shù)模板參數(shù)TTa;//…}12.5.2函數(shù)模板的實(shí)例化函數(shù)模板的實(shí)例化不需要用戶顯式進(jìn)行,而是在函數(shù)調(diào)用時(shí)由編譯器來(lái)處理。voidmain(){inta,b;charc,d;intm1=max(a,b);//調(diào)用max(inta,intb);charm2=max(c,d);//調(diào)用max(charc,chard);}

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論