錢能C 程序設(shè)計(jì)教程12_第1頁
錢能C 程序設(shè)計(jì)教程12_第2頁
錢能C 程序設(shè)計(jì)教程12_第3頁
錢能C 程序設(shè)計(jì)教程12_第4頁
錢能C 程序設(shè)計(jì)教程12_第5頁
已閱讀5頁,還剩15頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

C++程序設(shè)計(jì)教程(第二版)第十二章

多態(tài)Chapter12

Polymorphism

清華大學(xué)出版社

錢能4/18/20231第十章內(nèi)容繼承召喚多態(tài)(InheritanceSummonupPolymorphism)

抽象編程的困惑(AbstractProgrammingPerplexing)

虛函數(shù)(VirtualFunction)

避免虛函數(shù)誤用(AvoidingMisusingVirtualFunction)

精簡共性的類(SimplifyClasswithGenerality)

多態(tài)編程(PolymorphicProgramming)

類型轉(zhuǎn)換(TypeConversions

)4/18/202321.繼承召喚多態(tài)(InheritanceSummonupPolymorphism)

祖孫互易的說明:晚輩是前輩的后繼,晚輩是前輩的一種.反之不確,前輩不是晚輩,也不是晚輩的一種.這一概念也影響到類的繼承操作,甚至其指針操作:Student是GraduateStudent的祖先.則:Students,*pS;GraduateStudent

gs,*pGS;s=gs;//okgs=s;//errorpS=static_cast<Student*>(&gs);//okpGS=static_cast<GraduateStudent*>(&s);//error4/18/20233同化效應(yīng)

classStudent{public://...voiddisplay(){cout<<“UnderGraduate\n”;}};classGraduateStudent:publicStudent{public://...voiddisplay(){cout<<“Graduate\n";}};Studentds;GraduateStudent

gs;ds.display();gs.display();對于右邊的類和對象操作,則有下列結(jié)果:UnderGraduateGraduate但是,若執(zhí)行s=gs;則執(zhí)行s.display()的結(jié)果為:UnderGraduate說明,gs雖然是研究生對象,但在賦值給大學(xué)生對象操作之后,被大學(xué)生同化了,喪失了研究生的本性.4/18/20234同化效應(yīng)蔓延到指針操作

Students,*ps;GraduateStudent

gs;ps=&s;ps->display();ps=static_cast<Student*>(&gs);ps->display();結(jié)果:UnderGraduateGraduate這意味著子類對象就是父類對象的性質(zhì)是一句空話.因?yàn)椴僮髌饋碓瓉硎菍⒆宇悓ο蟠直┑耐?,根本扼殺了子類對象的個(gè)性.于是,子類對象與父類對象共存的容器便失去了意義,因?yàn)槿萜髦袥]有子類對象,全部同化成一種父類對象了,世界失去了豐富多彩性!4/18/20235關(guān)鍵技術(shù)

voidfn(Student&x){//...}intmain(){Students;

GraduateStudent

gs;

fn(s);//顯示大學(xué)生信息

fn(gs);//顯示研究生信息}結(jié)果:UnderGraduateGraduate子類對象賦值給父類對象,使得子類對象不復(fù)存在,這沒有異議.Students=gs;否則,讓父類對象行使子類職能就太離譜了.當(dāng)子類對象的地址賦給父類對象指針(或引用)時(shí),應(yīng)讓子類對象維持其狀態(tài)的完整性,并且還要顯露其子類的特征.即多態(tài)性:4/18/202362.抽象編程的困惑(AbstractProgrammingPerplexing)類型域方案可以做到,即實(shí)現(xiàn)fn函數(shù)如下:void

fn(Student&x){

switch(x.type){

case

Student::STUDENT:

x.calcTuition();break;

case

Student::GRADUATESTUDENT:

GraduateStudent&rx=static_cast<GraduateStudent&>(x);

rx.calcTuition();break;}}但不敢恭維這種方法,因?yàn)樗鼘?dǎo)致類編程與應(yīng)用編程互相依賴,因而破壞了只關(guān)注局部細(xì)節(jié)的抽象編程.4/18/20237破壞抽象編程的后果是:可維護(hù)性,可擴(kuò)展性受到傷害.若增加一個(gè)博士類,則類代碼與應(yīng)用程序代碼都得改,而這本來不是應(yīng)用程序的份內(nèi)事.因而呼吁從語言內(nèi)部來支持這種多態(tài)性.4/18/202383.虛函數(shù)(VirtualFunction)

于是應(yīng)用程序便有多態(tài),而且fn函數(shù)實(shí)現(xiàn)非常簡捷:

void

fn(Student&x){

x.display()

}

intmain(){

Students;

GraduateStudent

gs;

fn(s);//顯示大學(xué)生信息

fn(gs);//顯示研究生信息

}

結(jié)果:

UnderGraduate

Graduate類中采用虛函數(shù):

classStudent{

public:

virtualvoiddisplay(){

cout<<“UnderGraduate\n”;

}

};

class

GraduateStudent

:publicStudent{

public:

virtualvoiddisplay(){

cout<<“Graduate\n”;

}

};

注:子類同名函數(shù)上的virtual可省4/18/20239多態(tài)性使得應(yīng)用程序使用類體系中的祖孫對象共存的復(fù)雜局面達(dá)到了一種編程自在境界.

程序員從使用孤立的類(抽象數(shù)據(jù)類型),到使用分層的類,并且讓各種對象“同場競技”,充分展現(xiàn)其個(gè)性.嘗到了對象化編程的真正樂趣.

C++類機(jī)制的虛函數(shù)就是沖著讓類編程實(shí)質(zhì)性地支持應(yīng)用編程中對家族化對象操作依賴的目的,從而面向?qū)ο髞矸治觥⒃O(shè)計(jì)和解決問題.4/18/2023104.避免誤用虛函數(shù)(AvoidingMisusingVirtualFunction)

classBase{public:

virtualvoid

fn(intx){

cout<<"Base\n";}};classSub:publicBase{public:

virtualvoid

fn(doublex){

cout<<"Sub\n";}};void

test(Base&b){b.fn(3.5);}intmain(){

test(Base());

test(Sub());}子類重載父類成員函數(shù)不能傳播“虛”性

右邊程序的運(yùn)行結(jié)果說明了這一點(diǎn):

BaseBase4/18/202311函數(shù)重載對于編譯識(shí)別來說,返回類型是不起作用的.voidfn(int);int

fn(int);對于fn(2);無法判斷應(yīng)該調(diào)用哪個(gè)函數(shù).而使調(diào)用遭遇編譯失?。畬τ谔摵瘮?shù)來說,聲明:virtualBase*fn();virtualSub*fn();應(yīng)看作不能分辨其多態(tài)調(diào)用的虛函數(shù),但卻引編譯認(rèn)為是同一個(gè)虛函數(shù)而獲得通過.這是語言技術(shù)上的一種處理,事實(shí)上,如果一個(gè)多態(tài)函數(shù)正在處理Sub類的對象,則它仍可以通過返回的Sub對象指針,繼續(xù)處理Sub對象,似乎更自然4/18/202312注意事項(xiàng):多態(tài)性是通過成員函數(shù)捆綁不同類型的對象來體現(xiàn)的,所以,虛函數(shù)一定是成員函數(shù),而且,靜態(tài)成員函數(shù)都不行,因?yàn)樗焕墝ο?,同樣,?gòu)造函數(shù)也不行,因?yàn)樗划a(chǎn)生對象,也不捆綁對象.可是,析構(gòu)函數(shù)卻可以是虛函數(shù),事實(shí)上,鼓勵(lì)類繼承體系中的每個(gè)類最好其析構(gòu)函數(shù)都是虛函數(shù).一旦設(shè)置了虛函數(shù),就與編譯器達(dá)成了滯后聯(lián)編的協(xié)議,函數(shù)必定分離于當(dāng)前運(yùn)行的模塊,因而就不可能是內(nèi)聯(lián)函數(shù)了.4/18/2023135.精簡共性的類(SimplifyClasswithGenerality)孤立的類之間有一些共性,希望減少一些冗余代碼.通常不能因此而構(gòu)成上下級(jí)關(guān)系的類層次,因?yàn)闀?huì)產(chǎn)生不良反應(yīng):基類如果擴(kuò)展功能,勢必連累子類.4/18/2023146.多態(tài)編程(PolymorphicProgramming)將共性的類通過繼承由共性構(gòu)成的基類來實(shí)現(xiàn)或許會(huì)比較明智.因?yàn)閮烧叩臄U(kuò)展彼此之間不會(huì)帶來干擾.而且還可任意派生子類類的繼承體系決定之后,其基類的多態(tài)成員函數(shù)也可確定.通??梢栽谧宇愔g進(jìn)行比較,同名不同功能的函數(shù)往往可以置成虛函數(shù).classAccount{protected://...public:virtualvoiddisplay()const;virtualvoidwithdrawal(doubleamount){}};4/18/202315多態(tài)編程中,會(huì)遇到各種子類混在一個(gè)集合中的情形,這正是多態(tài)大展身手的時(shí)候.針對左邊的類體系,有多態(tài)的應(yīng)用代碼:vector<shape*>a;//...for(inti=0;i<a.size();++i)

a[i]->area();classShape{public://...

virtualvoidarea(){}};class

Circle:publicShape{public:

voidarea(){…}//...};class

Triangle:publicShape{public:

voidarea(){…}//...};//...4/18/2023167.類型轉(zhuǎn)換(TypeConversions

)調(diào)用虛函數(shù)是一種多態(tài)的方法,它是將運(yùn)行中無法知道的對象交給系統(tǒng)去自動(dòng)辨認(rèn)類型從而作出準(zhǔn)確的操作使用動(dòng)態(tài)轉(zhuǎn)型策略:另一種實(shí)現(xiàn)是在運(yùn)行中,判斷對象的類型,從而可以準(zhǔn)確的捆綁調(diào)用確定的成員函數(shù),這是一種主動(dòng)辨認(rèn)對象類型的編程策略4/18/202317辨認(rèn)對象的類型,首先應(yīng)該知道其屬于哪個(gè)類系.然后確定要判斷的子類名稱.再行編碼.例如,針對每個(gè)對象進(jìn)行操作:Savings類對象,余額增加以1%計(jì)算的利息;Checking類對象,余額增加以0.05%計(jì)算的利息vector<Account*>a;//...Checking*pC;Savings*pS;for(inti=0;i<a.size();++i){

if(pC=dynamic_cast<Checking*>(a[i]))

pC->deposit(pC->getBalan()*0.05);

elseif(pS=dynamic_cast<Savings*>(&a[i]))

pS->deposit(pS->getBalan()*0.1);

a[i]->display();}動(dòng)態(tài)轉(zhuǎn)型4/18/202318動(dòng)態(tài)轉(zhuǎn)型只限于多態(tài)類,而靜態(tài)轉(zhuǎn)型適合更一般的類對象.例如,沒有多態(tài)性的學(xué)生與研究生之間的轉(zhuǎn)換:Student*ps=static_cast<Student*>(&gs);例如:無類型指針到某類型指針的轉(zhuǎn)換:

void

fn(void*dd){Student*pp=static_cast<Student*>(&dd);//...}靜態(tài)轉(zhuǎn)型4/18/202319許多標(biāo)準(zhǔn)類庫函數(shù)的聲明為了適應(yīng)大多數(shù)編程場合,做了完美的設(shè)計(jì).例如,max:constchar*max(constchar*s1,constchar*s2){

returnstrcmp(s1,s2)>0?s1:

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論