版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
C++語言程序設(shè)計第十一組C++語言程序設(shè)計第十章多態(tài)C++語言程序設(shè)計1目錄C++語言程序設(shè)計2“多態(tài)的概念運行時多態(tài)模板基本知識函數(shù)模板運行時多態(tài)編程技能重載與靜態(tài)聯(lián)編覆蓋與靜態(tài)聯(lián)編虛函數(shù)與動態(tài)聯(lián)編刨根問底C++語言程序設(shè)計3基本知識a10.1多態(tài)的概念多態(tài)(Polymorphism)是程序設(shè)計語言的一個重要特征。類比:不同的人對同一事件會做出不同的反應(yīng)多態(tài)性要求相同的標(biāo)識符(一般是函數(shù)名)在不同的場合使用時,表現(xiàn)出不同的行為或特性?!昂瘮?shù)重載”和“運算符重載”都是多態(tài)性的表現(xiàn)。面向?qū)ο蟪绦蛟O(shè)計中的多態(tài)性表現(xiàn)為以下3種形式:(1)重載多態(tài):包括函數(shù)重載、運算符重載。(2)運行多態(tài):通過基類的指針(或引用),調(diào)用不同派生類的同名函數(shù),表現(xiàn)出不同的行為。(3)模板多態(tài):即參數(shù)多態(tài),通過一個模板得到不同的函數(shù)或不同的類。這些函數(shù)或者類具有不同的特性和不同的行為。C++語言程序設(shè)計410.1多態(tài)的概念聯(lián)編(Binding,也叫“綁定”)。如果主程序調(diào)用子程序的語句是多態(tài)性語句,那么在執(zhí)行調(diào)用之前,主程序必須得確定子程序的地址(或者說,確定調(diào)用哪個子程序),這個過程稱為聯(lián)編聯(lián)編有兩種方式:靜態(tài)聯(lián)編在源程序編譯的時候就能確定具有多態(tài)性的語句調(diào)用哪個函數(shù)動態(tài)聯(lián)編在程序運行時才能夠確定具有多態(tài)性的語句究竟調(diào)用哪個函數(shù)運行時多態(tài)C++語言程序設(shè)計510.1多態(tài)的概念C++語言程序設(shè)計6聯(lián)編與多態(tài)之間的關(guān)系10.2運行時多態(tài)#include<iostream>usingnamespacestd;classB{public:voidf(){cout<<"B"<<endl;}};classP:publicB{public:voidf(){cout<<"P"<<endl;}};classQ:publicB{public:voidf(){cout<<"Q"<<endl;}};voidmain(){B*b_ptr; Pp; Qq;b_ptr=&p;b_ptr->f();b_ptr=&q;b_ptr->f();}C++語言程序設(shè)計7運行結(jié)果:BB雖然基類指針指向了不同的派生類對象,但調(diào)用同名函數(shù)時依然是基類的函數(shù)10.2運行時多態(tài)C++語言程序設(shè)計8在同名覆蓋現(xiàn)象中,通過某個類的對象(對象指針、對象引用)調(diào)用同名函數(shù),編譯器會將該調(diào)用靜態(tài)聯(lián)編到該類的同名函數(shù)。通過基類對象指針(引用)是無法訪問派生類的同名函數(shù)的,即便這個指針(引用)是使用派生類對象來初始化的。如何打破上面的限制,使得通過基類對象指針可以訪問派生類的同名函數(shù)?將基類中的同名函數(shù)定義為虛函數(shù)。編譯器無法在編譯時確定調(diào)用哪個同名函數(shù),只有在程序運行的時候,才能確定被調(diào)函數(shù),也就是需要動態(tài)聯(lián)編10.2運行時多態(tài)C++語言程序設(shè)計9虛函數(shù)virtual<返回值類型>函數(shù)名(參數(shù)表);基類中的同名函數(shù)聲明為虛函數(shù)后,派生類的同名函數(shù)(同返回值、同參數(shù))無論是否用virtual關(guān)鍵字說明,都將自動成為虛函數(shù)。10.2運行時多態(tài)#include<iostream>usingnamespacestd;classB{public:virtualvoidf(){cout<<"B"<<endl;}};classP:publicB{public:voidf(){cout<<"P"<<endl;}};classQ:publicB{public:voidf(){cout<<"Q"<<endl;}};voidmain(){B*b_ptr; Pp; Qq;b_ptr=&p;b_ptr->f();b_ptr=&q;b_ptr->f();}C++語言程序設(shè)計10運行結(jié)果:PQ基類指針指向了不同的派生類對象,調(diào)用的同名函數(shù)是各對應(yīng)派生類的函數(shù),而非基類的函數(shù)10.2運行時多態(tài)C++語言程序設(shè)計11要實現(xiàn)運行時的多態(tài),需要以下條件:(1)必須通過指向基類對象的指針,訪問和基類成員函數(shù)同名的派生類成員函數(shù)?;蛘哂门缮悓ο蟪跏蓟幕悓ο蟮囊茫L問和基類成員函數(shù)同名的派生類成員函數(shù)。(2)派生類的繼承方式必須是公有繼承。(3)基類中的同名成員函數(shù)必須定義為虛函數(shù)。10.2運行時多態(tài)C++語言程序設(shè)計12使用虛函數(shù)時要遵循以下規(guī)則:(1)必須首先在基類中聲明虛函數(shù)。(2)基類和派生類的同名函數(shù),函數(shù)名、返回值、參數(shù)表必須全部相同。(3)靜態(tài)成員函數(shù)不可以聲明為虛函數(shù)。構(gòu)造函數(shù)也不可以聲明為虛函數(shù)。(4)析構(gòu)函數(shù)可以聲明為虛函數(shù),即可以定義虛析構(gòu)函數(shù)。(5)多層繼承中,最高層中聲明為虛函數(shù)的,后續(xù)層若定義了同名函數(shù),則也是虛函數(shù)。這種關(guān)系不會因為中間層沒有定義這個函數(shù)而受到影響。10.2運行時多態(tài)#include<iostream>usingnamespacestd;classB{public:virtualvoidf(){cout<<"B"<<endl;}};classP:publicB{public:voidf(inta){cout<<"P"<<endl;}};classQ:publicB{public:voidf(){cout<<"Q"<<endl;}};voidmain(){B*b_ptr; Pp; Qq;b_ptr=&p;b_ptr->f(1);b_ptr=&q;b_ptr->f();}C++語言程序設(shè)計13基類和派生類的同名函數(shù),函數(shù)名、返回值、參數(shù)表必須全部相同。錯誤10.2運行時多態(tài)#include<iostream>usingnamespacestd;classB{public:virtualvoidf(){cout<<"B"<<endl;}};classP:publicB{public:voidf(inta){cout<<"P"<<endl;}};classQ:publicP{public:voidf(){cout<<"Q"<<endl;}};voidmain(){B*b_ptr;
Qq;
b_ptr=&q;b_ptr->f();}C++語言程序設(shè)計14運行結(jié)果:Q多層繼承中,最高層中聲明為虛函數(shù)的,后續(xù)層若定義了同名函數(shù),則也是虛函數(shù)。這種關(guān)系不會因為中間層沒有定義這個函數(shù)而受到影響。10.2運行時多態(tài)C++語言程序設(shè)計15普通的析構(gòu)函數(shù):在創(chuàng)建派生類對象時,首先會調(diào)用基類的構(gòu)造函數(shù),然后執(zhí)行派生類構(gòu)造函數(shù)。在釋放派生類對象時,將首先執(zhí)行派生類的析構(gòu)函數(shù),再調(diào)用基類的析構(gòu)函數(shù)。如果使用new運算符動態(tài)創(chuàng)建派生類對象,并以此對象的地址初始化基類的指針創(chuàng)建過程不會有問題,仍然是先調(diào)用基類構(gòu)造函數(shù),再執(zhí)行派生類構(gòu)造函數(shù)。在用delete運算符刪除派生類對象的時候,由于指針是指向基類的,通過靜態(tài)聯(lián)編,只會調(diào)用基類的析構(gòu)函數(shù)10.2運行時多態(tài)C++語言程序設(shè)計16虛析構(gòu)函數(shù):將基類析構(gòu)函數(shù)設(shè)置為虛函數(shù),則派生類的析構(gòu)函數(shù)自動均為虛函數(shù)使用new運算符動態(tài)創(chuàng)建派生類對象,并以此對象的地址初始化基類的指針創(chuàng)建仍然是先調(diào)用基類構(gòu)造函數(shù),再執(zhí)行派生類構(gòu)造函數(shù)。在用delete運算符刪除派生類對象(基類指針)的時候,派生類先執(zhí)行自己的析構(gòu)函數(shù),再調(diào)用基類的析構(gòu)函數(shù)10.2運行時多態(tài)#include<iostream>usingnamespacestd;classB{public:~B(){cout<<“~B"<<endl;}};classP:publicB{public:~P(){cout<<“~P"<<endl;}};voidmain(){B*b_ptr=newP;
deleteb_ptr;}C++語言程序設(shè)計17運行結(jié)果:~B僅僅執(zhí)行了基類的析構(gòu)函數(shù)。10.2運行時多態(tài)#include<iostream>usingnamespacestd;classB{public:virtual~B(){cout<<“~B"<<endl;}};classP:publicB{public:~P(){cout<<“~P"<<endl;}};voidmain(){B*b_ptr=newP;
deleteb_ptr;}C++語言程序設(shè)計18運行結(jié)果:~D~B基類中是虛析構(gòu)函數(shù),所以釋放對象時先執(zhí)行派生類析構(gòu)函數(shù),再執(zhí)行基類的析構(gòu)函數(shù)。10.2運行時多態(tài)C++語言程序設(shè)計19純虛函數(shù):在C
++
中,對于那些在基類中不需要定義具體行為的函數(shù),可以聲明為純虛函數(shù)。virtual<返回值類型>函數(shù)名(參數(shù)表)=0;純虛函數(shù)特點:(1)純虛函數(shù)一定是在基類中聲明的。(2)在多級繼承的情況下,純虛函數(shù)可以在各層類中聲明。(3)純虛函數(shù)是沒有函數(shù)體的,函數(shù)體用“=
0”來代替。(4)純虛函數(shù)不可以被調(diào)用。凡是需要被調(diào)用的函數(shù)都不可以聲明為純虛函數(shù)。10.2運行時多態(tài)C++語言程序設(shè)計20抽象類:凡是帶有一個或多個純虛函數(shù)的類,就是抽象類。抽象類的定義是基于純虛函數(shù)的。對于那些只是反映一類事物公共特性的類,在C
++
中可以定義為抽象類。抽象類特點:(1)抽象類不可以實例化(2)可以定義抽象類的指針和抽象類的引用。目的是通過這些指針或引用訪問派生類的虛函數(shù),實現(xiàn)運行時的多態(tài)。這些指針和引用都只能用派生類對象來初始化。(3)如果抽象類的派生類中沒有具體實現(xiàn)純虛函數(shù)的功能,這樣的派生類仍然是抽象類。(4)抽象類中除了純虛函數(shù)外,還可以定義其他的非純虛函數(shù)。
10.3模
板C++語言程序設(shè)計21模板是C++
中的通用程序模塊。在這些程序模塊中,有一些數(shù)據(jù)類型是不具體的,或者說是抽象的。當(dāng)這些抽象的數(shù)據(jù)類型更換為不同的具體數(shù)據(jù)類型以后,就會產(chǎn)生一系列具體的程序模塊。這些抽象的數(shù)據(jù)類型稱為“參數(shù)化類型”(ParameterizedTypes)。C++
中的模板:函數(shù)模板:會產(chǎn)生一系列參數(shù)類型不同的函數(shù),實例化后產(chǎn)生的函數(shù),稱為模板函數(shù)類模板:會產(chǎn)生一系列不同參數(shù)的類,實例化后產(chǎn)生的類,稱為模板類。
10.3模
板C++語言程序設(shè)計22函數(shù)模版函數(shù)模板是函數(shù)重載概念的發(fā)展和延伸函數(shù)模板像是一個函數(shù)發(fā)生器,使用具體的數(shù)據(jù)類型取代模板中的參數(shù)化類型,即可得到一個個具體的函數(shù)。這種通過類型取代獲得的多態(tài),屬于參數(shù)多態(tài)。template<typename參數(shù)化類型名>函數(shù)返回類型函數(shù)名(形式參數(shù)列表){
函數(shù)體
}template<typenameT>Tmax_value(Tx,Ty,Tz){Ttemp=x>y?x:y;returntemp>z?temp:z;}關(guān)鍵字“typename”可以用“class”取代
10.3模
板C++語言程序設(shè)計23//Main10.cpp#include<iostream>usingnamespacestd;template<typenameT>Tmax_value(Tx,Ty,Tz){
Ttemp=x>y?x:y;returntemp>z?temp:z;}intmain(){cout<<max_value(12,32,21)<<endl;//用整數(shù)作實參調(diào)用函數(shù)模板
cout<<max_value('a','A','9')<<endl; //用字符作實參調(diào)用函數(shù)模板
return0;}
10.3模
板C++語言程序設(shè)計24函數(shù)模版,參數(shù)化類型名可以不止一個#include<iostream>usingnamespacestd;template<typenameP1,typenameP2>P1cal(P1x,P2y){ //函數(shù)模板有兩個參數(shù)化類型名:P1和P2return(x*static_cast<P1>(y)); //按x的數(shù)據(jù)類型執(zhí)行乘法運算
}intmain(){unsignedshortw=230;shortz=150;cout<<cal(w,z)<<endl; //按無符號數(shù)相乘
cout<<cal(z,w)<<endl; //按有符號數(shù)相乘
}程序運行結(jié)果是:34500-31036
10.3模
板C++語言程序設(shè)計25帶有確定類型參數(shù)的函數(shù)模板函數(shù)模板的參數(shù)表中,一定要包含參數(shù)化類型名,但不一定只使用參數(shù)化類型名,還可以根據(jù)需要,使用確定類型的參數(shù)。template<classQ1> voidArrayInput(Q1array,intnum){cout<<"輸入"<<num<<"個"<<typeid(Q1).name()<<'\b'<<"型數(shù)據(jù)"<<endl;for(intj=0;j<num;j++)
cin>>array[j]; //輸入數(shù)組元素
}
10.3模
板C++語言程序設(shè)計26typeid運算符在程序運行時,顯示指定的數(shù)據(jù)的類型。 typeid(表達式).name()或typeid(類型標(biāo)識符).name()執(zhí)行的結(jié)果是返回“表達式”或者“類型標(biāo)識符”的類型名。
intnumber;floatfloatArray[4];intintArray[3];number=sizeof(floatArray)/sizeof(float);ArrayInput(floatArray,number); number=sizeof(intArray)/sizeof(int);ArrayInput(intArray,number);輸入4個float型數(shù)據(jù)1.12.23.34.4輸入3個int型數(shù)據(jù)
567typeid(floatArray).name()返回的是float*typeid(intArray).name()返回的是int*
10.3模
板C++語言程序設(shè)計27類模板template<class參數(shù)化類型名1,…,class參數(shù)化類型名n>class類名{
數(shù)據(jù)成員定義;
成員函數(shù)原型;};template<classT1,classT2>classMyClass{private:T1x;T2y;public:MyClass(T1a,T2b);voiddisplay();};
10.3模
板C++語言程序設(shè)計28intmain(){MyClass<int,float>Obj1(6,6.6);Obj1.display();MyClass<char,char*>Obj2('x',"Astring");Obj2.display();}template<classT1,classT2>MyClass<T1,T2>::MyClass(T1a,T2b){x=a;y=b;}template<classT1,classT2>voidMyClass<T1,T2>::display(){cout<<x<<endl;cout<<y<<endl;}
10.3模
板C++語言程序設(shè)計29帶有確定類型參數(shù)的類模板
template<classT,inti>classMyStackMyStack<int,5>Obj1;在類模板實例化和聲明對象時,參數(shù)i用具體的整型值來代替C++語言程序設(shè)計編程技能b30(一)函數(shù)模板C++語言程序設(shè)計31用戶定義的類取代參數(shù)化類型template<typenameT>Tmax_value(Tx,Ty,Tz){
Ttemp;if(x>y)temp=x;elsetemp=y;if(z>temp)temp=z;returntemp;}classCircle{public:
friendostream&operator<<(ostream&,Circle&);Circle(inta=0,intb=0,doublec=0.0)
{x=a;y=b;radius=c;
}intoperator>(Circlem2){ if(radius>m2.radius)return1;
elsereturn0;}private:intx,y; //圓心坐標(biāo)
doubleradius; //圓半徑
}; (一)函數(shù)模板C++語言程序設(shè)計32用戶定義的類取代參數(shù)化類型ostream&operator<<(ostream&out,Circle&C1){out<<"x="<<C1.x<<"y="<<C1.y;out<<"radius="<<C1.radius;returnout;}intmain(){CircleC1(2,3,5),C2(3,5,8),C3(3,2,6);
cout<<max_value(12,32,21)<<endl;
cout<<max_value('a','A','9')<<endl;
cout<<max_value(C1,C2,C3)<<endl;}(一)函數(shù)模板C++語言程序設(shè)計33函數(shù)模板不支持參數(shù)自動轉(zhuǎn)換定義:
intadd(inta,intb);由于參數(shù)可以自動轉(zhuǎn)換,以下函數(shù)調(diào)用都是合法的:add(2.5,4.4);add('a','d');add('a',18);定義:template<typenameT>Tmax_value(Tx,Ty,Tz);以下函數(shù)調(diào)用是錯誤的:max_value(12,3.2,21);(一)函數(shù)模板C++語言程序設(shè)計34重載函數(shù)模板同時如下定義,構(gòu)成重載:
intadd(inta,intb,intc);template<typenameT>Tmax_value(Tx,Ty,Tz);重載函數(shù)模板的匹配過程是按照以下順序來進行的:(1)尋找函數(shù)名和參數(shù)能準(zhǔn)確匹配的非模板函數(shù)。(2)如果沒有找到,選擇參數(shù)可以匹配的函數(shù)模板。(3)如果還不成功,通過參數(shù)自動轉(zhuǎn)換,選擇非模板函數(shù)。(二)運行時多態(tài)C++語言程序設(shè)計35運行時多態(tài)有什么用?pB->Draw();同一條語句,但每次調(diào)用執(zhí)行的可能都是不同的函數(shù):
增加了程序的可擴展性和可維護性(二)運行時多態(tài)C++語言程序設(shè)計36注意虛析構(gòu)函數(shù)的作用
派生類堆對象的地址存儲到基類指針中,delete操作時,若需要執(zhí)行派生類的析構(gòu)函數(shù),則必須設(shè)置為虛析構(gòu)函數(shù)刨根問底cC++語言程序設(shè)計37(I)
重載與靜態(tài)聯(lián)編C++語言程序設(shè)計38函數(shù)重載:編譯器根據(jù)函數(shù)的參數(shù)能夠確定每次調(diào)用哪個函數(shù)intadd(inta){returna+10;}intadd(inta,intb){returna+b;}intmain(){intx=1,y=2;add(x);add(x,y);return0;}經(jīng)過編譯器處理之后,同名的函數(shù)變成了不同地址的子程序?qū)ν瘮?shù)的調(diào)用變成了對不同地址子程序的調(diào)用這個轉(zhuǎn)變過程是由編譯器完成的編譯器分辨出了同名函數(shù)的不同之處。屬于靜態(tài)聯(lián)編(II)
覆蓋與靜態(tài)聯(lián)編C++語言程序設(shè)計39函數(shù)覆蓋:只出現(xiàn)在繼承樹中在派生類中定義和基類中同名的成員函數(shù),是對基類進行改造,為派生類增加新行為的一種常用的方法。通過不同的派生類的對象(對象指針或者對象引用),調(diào)用這些同名的成員函數(shù),實現(xiàn)不同的操作,也是多態(tài)性的一種表現(xiàn)。被派生類覆蓋的函數(shù)是否是虛函數(shù):是虛函數(shù)——動態(tài)聯(liá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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 六盤水師范學(xué)院《農(nóng)民畫綜合材料創(chuàng)作》2023-2024學(xué)年第一學(xué)期期末試卷
- 焦作師范高等專科學(xué)?!睹佬g(shù)課程設(shè)計與開發(fā)》2023-2024學(xué)年第一學(xué)期期末試卷
- 新蘇教版一年級下冊數(shù)學(xué)第1單元第1課時《9加幾》作業(yè)
- 華中師范大學(xué)《網(wǎng)球(2)》2023-2024學(xué)年第一學(xué)期期末試卷
- 【物理】第八章 運動和力+2024-2025學(xué)年人教版(2024)物理八年級下冊
- 河套學(xué)院《環(huán)境健康密碼》2023-2024學(xué)年第一學(xué)期期末試卷
- 重慶輕工職業(yè)學(xué)院《計算機組成及系統(tǒng)結(jié)構(gòu)》2023-2024學(xué)年第一學(xué)期期末試卷
- 駐馬店職業(yè)技術(shù)學(xué)院《制冷與空調(diào)》2023-2024學(xué)年第一學(xué)期期末試卷
- 浙江藥科職業(yè)大學(xué)《數(shù)值模擬技術(shù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 浙江工商大學(xué)《多媒體數(shù)據(jù)分析與檢索》2023-2024學(xué)年第一學(xué)期期末試卷
- 綿陽市高中2022級(2025屆)高三第二次診斷性考試(二診)歷史試卷(含答案)
- 四年級數(shù)學(xué)(上)計算題專項練習(xí)及答案
- 軍事理論(2024年版)學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- GB/T 6672-2001塑料薄膜和薄片厚度測定機械測量法
- 福建師范大學(xué)(答案)課程考試2023年2月《刑事訴訟法》作業(yè)考核試題
- 寫人事物景作文課件
- 廠級安全培訓(xùn)資料
- 中國藥科大學(xué)《藥物化學(xué)》教學(xué)日歷
- 露天礦山課件
- 經(jīng)濟效益證明(模板)
- 果樹蔬菜病害:第一章 蔬菜害蟲
評論
0/150
提交評論