




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第C++的多態(tài)與虛函數(shù)你了解嗎目錄多態(tài)性虛函數(shù)總結(jié)
多態(tài)性
多態(tài)性是面向?qū)ο蟪绦蛟O(shè)計(jì)的關(guān)鍵技術(shù)之一,若程序設(shè)計(jì)語(yǔ)言不支持多態(tài)性,不能稱(chēng)為面向?qū)ο蟮恼Z(yǔ)言,利用多態(tài)性技術(shù),可以調(diào)用同一個(gè)函數(shù)名的函數(shù),實(shí)現(xiàn)完全不同的功能
在C++中有兩種多態(tài)性:
編譯時(shí)的多態(tài)
通過(guò)函數(shù)的重載和運(yùn)算符的重載來(lái)實(shí)現(xiàn)的
運(yùn)行時(shí)的多態(tài)性
運(yùn)行時(shí)的多態(tài)性是指在程序執(zhí)行前,無(wú)法根據(jù)函數(shù)名和參數(shù)來(lái)確定該調(diào)用哪一個(gè)函數(shù),必須在程序執(zhí)行過(guò)程中,根據(jù)執(zhí)行的具體情況來(lái)動(dòng)態(tài)地確定;它是通過(guò)類(lèi)繼承關(guān)系public和虛函數(shù)來(lái)實(shí)現(xiàn)的,目的也是建立一種通用的程序;通用性是程序追求的主要目標(biāo)之一
通過(guò)引用或指針調(diào)用時(shí),才可以達(dá)到運(yùn)行時(shí)的多態(tài)
虛函數(shù)
虛函數(shù)是一個(gè)類(lèi)的成員函數(shù),定義格式如下:
virtual返回類(lèi)型函數(shù)名(參數(shù)表);
關(guān)鍵字virtual指明該成員函數(shù)為虛函數(shù),virtual僅用于類(lèi)定義中,如虛函數(shù)在類(lèi)外定義,不可加virtual
我們來(lái)看下面代碼
classAnimal
private:
stringname;
public:
Animal(conststringna):name(na)
public:
virtualvoideat(){}
virtualvoidwalk(){}
virtualvoidtail(){}
virtualvoidPrintInfo(){}
stringget_name()
returnname;
conststringget_name()const
returnname;
classDog:publicAnimal
private:
stringowner;
public:
Dog(conststringow,conststringna):Animal(na),owner(ow)
virtualvoideat()
cout"DogEat:bone"endl;
virtualvoidwalk()
cout"DogWalk:run"endl;
virtualvoidtail()
cout"DogTail:wangwang"endl;
virtualvoidPrintInfo()
cout"Dogowner"ownerendl;
cout"Dogname:"get_name()endl;
classCat:publicAnimal
private:
stringowner;
public:
Cat(conststringow,conststringna):Animal(na),owner(ow)
virtualvoideat()
cout"CatEat:fish"endl;
virtualvoidwalk()
cout"CatWalk:silent"endl;
virtualvoidtail()
cout"CatTail:miaomiao"endl;
virtualvoidPrintInfo()
cout"Catowner:"ownerendl;
cout"Catname:"get_name()endl;
//需要公有繼承公有繼承代表是一個(gè)的意思
//需要引用或指針調(diào)用
voidfun(Animalanimal)
animal.eat();//對(duì)象名稱(chēng).虛方法()
animal.walk();
animal.tail();
animal.PrintInfo();
intmain()
Dogdog("zyq","hashiqi");//conststringow="zyq"
Catcat("zyq","bosimao");
fun(dog);
fun(cat);
return0;
在這里我們可以看到,當(dāng)我們調(diào)用fun()函數(shù)時(shí),傳入dog對(duì)象則調(diào)用Dog的方法,傳入cat調(diào)用Cat方法;這就是所謂的運(yùn)行時(shí)的多態(tài)
要想達(dá)到運(yùn)行時(shí)的多態(tài)(晚綁定)需要滿(mǎn)足:
公有繼承有虛函數(shù)必須以指針或引用方式調(diào)用虛函數(shù)
若發(fā)生早綁定,則會(huì)調(diào)用Animal類(lèi)型的方法
成員函數(shù)應(yīng)盡可能的設(shè)置為虛函數(shù),但必須注意一下幾條:
1.派生類(lèi)中定義虛函數(shù)必須與基類(lèi)中的虛函數(shù)同名外,還必須同參數(shù)表,同返回類(lèi)型;否則被認(rèn)為是重載,而不是虛函數(shù)。如基類(lèi)中返回基類(lèi)指針,派生類(lèi)中返回派生類(lèi)指針是允許的,這是一個(gè)例外
2.只有類(lèi)的成員函數(shù)才能說(shuō)明為虛函數(shù),這是因?yàn)樘摵瘮?shù)僅適用于有繼承關(guān)系的類(lèi)對(duì)象
3.靜態(tài)成員函數(shù),是所有同一類(lèi)對(duì)象公有,不受限于某個(gè)對(duì)象,不能作為虛函數(shù)(友元函數(shù)也不可以)
4.實(shí)現(xiàn)動(dòng)態(tài)多態(tài)性時(shí),必須使用基類(lèi)類(lèi)型的指針變量或引用,使該指針指向該基類(lèi)的不同派生類(lèi)的對(duì)象,并通過(guò)該指針指向虛函數(shù),才能實(shí)現(xiàn)動(dòng)態(tài)的多態(tài)性
5.內(nèi)聯(lián)函數(shù)每個(gè)對(duì)象一個(gè)拷貝,無(wú)映射關(guān)系,不能作為虛函數(shù)
6.析構(gòu)函數(shù)可定義為虛函數(shù),構(gòu)造函數(shù)不可以定義為虛函數(shù),因?yàn)樵谡{(diào)用構(gòu)造函數(shù)時(shí)對(duì)象還沒(méi)有完成實(shí)例化;在基類(lèi)中及其派生類(lèi)中都動(dòng)態(tài)分配的內(nèi)存空間時(shí),必須把析構(gòu)函數(shù)定義為虛函數(shù),實(shí)現(xiàn)撤銷(xiāo)對(duì)象時(shí)的多態(tài)性
7.函數(shù)執(zhí)行速度要稍慢一些,為了實(shí)現(xiàn)多態(tài)性,每一個(gè)派生類(lèi)中均要保存相應(yīng)虛函數(shù)的入口地址表,函數(shù)的調(diào)用機(jī)制也是間接實(shí)現(xiàn);所以多態(tài)性總要付出一定代價(jià),但通用性是一個(gè)更高的目標(biāo)
8.如果定義放在類(lèi)外,virtual只能加在函數(shù)聲明前面,不能加載函數(shù)定義前面;正確的定義必須不包括virtual
虛函數(shù)是覆蓋,同名函數(shù)是隱藏
虛函數(shù)編譯過(guò)程
classObject
private:
intvalue;
public:
Object(intx=0):value(x)
virtualvoidadd()
cout"Object::add"endl;
virtualvoidfun()
cout"Object::fun"endl;
virtualvoidprint()const
cout"Object::print"endl;
classBase:publicObject
private:
intsum;
public:
Base(intx=0):Object(x+10),sum(x)
virtualvoidadd()
cout"Base::add"endl;
virtualvoidfun()
cout"Base::fun"endl;
virtualvoidprint()const
cout"Base::print"endl;
intmain()
此處虛函數(shù)表中進(jìn)行的是同名覆蓋,而不像繼承關(guān)系中,同名成員進(jìn)行隱藏,就近處理;虛函表僅有一份,存在數(shù)據(jù)區(qū)
在主函數(shù)創(chuàng)建對(duì)象
intmain()
Basebase(10);
Object*op=base;
可以看到base的大小為12字節(jié),因?yàn)槠渲谢?lèi)對(duì)象Object,添加了虛表變?yōu)榱?字節(jié),且在構(gòu)建過(guò)程,首先構(gòu)建Object基類(lèi),此時(shí)虛表指針指向Object的虛表,而接著構(gòu)建Base類(lèi)的時(shí)候,會(huì)將虛表指針修改為指向Base的虛表
也就是,當(dāng)有虛函數(shù)時(shí),構(gòu)造函數(shù)除了構(gòu)建對(duì)象初始化對(duì)象的數(shù)據(jù)成員外,還會(huì)將虛表的地址給到虛表指針;同時(shí)這也是構(gòu)造函數(shù)不可以作為虛函數(shù)的原因
intmain()
Basebase(10);
Object*op=NULL;
Objectobj(0);
op=base;
op-add();//指針或引用調(diào)動(dòng),則采用運(yùn)行時(shí)多態(tài)
op-fun();
op-print();
obj=base;
obj.add();//對(duì)象直接調(diào)動(dòng),則采用編譯時(shí)多態(tài)
obj.fun();
obj.print();
也就是我們通過(guò),對(duì)象名.方法的方式調(diào)用虛函數(shù),則通過(guò)編譯時(shí)多態(tài)的方式
運(yùn)行時(shí)的多態(tài),是通過(guò)查詢(xún)虛表進(jìn)行調(diào)用;下面通過(guò)匯編進(jìn)一步查看
只有進(jìn)行以指針調(diào)用或引用調(diào)用的時(shí)候才會(huì)對(duì)虛表進(jìn)行查詢(xún)
三層繼承
classObject
private:
intvalue;
public:
Object(intx=0):value(x)
virtualvoidadd()
cout"Object::add"endl;
virtualvoidfun()
cout"Object::fun"endl;
virtualvoidprint()const
cout"Object::print"endl;
voidfn_a()
fun();
classBase:publicObject
private:
intsum;
public:
Base(intx=0):Object(x+10),sum(x)
virtualvoidadd()
cout"Base::add"endl;
virtualvoidfun()
cout"Base::fun"endl;
virtualvoidshow()
cout"Base::show"endl;
classTest:publicBase
private:
intnum;
public:
Test(intx=0):Base(x+10)
virtualvoidadd()
cout"Test::add"endl;
virtualvoidprint()const
cout"Test::print"endl;
virtualvoidshow()
cout"Test::show"endl;
我們可以看到虛函數(shù)表,當(dāng)我們構(gòu)建派生類(lèi),會(huì)復(fù)制基類(lèi)的虛函數(shù)表,將虛表指針指向新的虛函數(shù)表,并且將同名的虛函數(shù)進(jìn)行覆蓋
依舊使用上面代碼
/*
voidfn_a()
fu
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 范文工程測(cè)量實(shí)習(xí)報(bào)告
- 區(qū)塊鏈技術(shù)驅(qū)動(dòng)的財(cái)務(wù)優(yōu)化策略
- 醫(yī)療領(lǐng)域中科研誠(chéng)信的倫理教育探索
- 建筑電氣畢業(yè)設(shè)計(jì)
- 大腦相關(guān)課件
- 行政管理專(zhuān)科必考試題及答案
- 行政法學(xué)考試中提高分?jǐn)?shù)的技巧與試題及答案
- 宜賓五糧液股份有限公司2025年上半年校園招聘(253人)筆試參考題庫(kù)附帶答案詳解
- 經(jīng)濟(jì)法常見(jiàn)疑難問(wèn)題解析試題及答案
- 統(tǒng)籌知識(shí)2025年試題及答案回顧
- 勞動(dòng)合同書(shū)范本介紹5篇
- 2025年“鑄牢中華民族共同體意識(shí)”競(jìng)賽試卷題庫(kù)及答案
- 2025年二級(jí)風(fēng)力發(fā)電運(yùn)維值班員職業(yè)技能鑒定考試題庫(kù)(濃縮500題)
- 《一帶一路主題樂(lè)園規(guī)劃》課件
- 江蘇省南京市、鹽城市2025屆高三年級(jí)5月第二次模擬考試化學(xué)試題及答案(南京鹽城二模)
- 2025新能源汽車(chē)技術(shù)的應(yīng)急管理策略試題及答案
- 八年級(jí)下學(xué)期家長(zhǎng)會(huì)課件《攜手同行共筑夢(mèng)想》
- 建筑勞務(wù)分包合同中的稅務(wù)問(wèn)題3篇
- 【課件】Unit+7+A+Day+to+Remember+Section+A(1a-1d)+課件+2024-2025學(xué)年人教版英語(yǔ)七年級(jí)下冊(cè)
- 2024-2025人教版一年級(jí)下冊(cè)數(shù)學(xué)期末考試卷附答案 (三套)
- 2024年國(guó)網(wǎng)吉林喆森產(chǎn)業(yè)管理有限公司招聘真題
評(píng)論
0/150
提交評(píng)論