




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第C++詳細(xì)講解繼承與虛繼承實(shí)現(xiàn)目錄繼承的概念及定義概念:定義:繼承關(guān)系和訪問限定符總結(jié)基類和派生類對(duì)象賦值轉(zhuǎn)換繼承中的作用域派生類的默認(rèn)成員函數(shù)繼承與友元繼承與靜態(tài)成員復(fù)雜的菱形繼承及菱形虛擬繼承虛繼承原理繼承的總結(jié)
繼承的概念及定義
概念:
繼承機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)為了提高代碼復(fù)用率的一種手段,它可以保持原類特性的基礎(chǔ)上進(jìn)行拓展,簡(jiǎn)單來說繼承是類層次的復(fù)用。
接下來我們來看一個(gè)簡(jiǎn)單的繼承
classPerson
public:
voidPrint()
cout"name:"_nameendl;
cout"age:"_ageendl;
protected:
string_name="zhao";
int_age=18;
classStudent:publicPerson
protected:
int_stuid;
classTeacher:publicPerson
protected:
int_jobid;
};
在上面這個(gè)類中繼承后父類(Person)的成員都會(huì)變成子類的一部分。
定義:
格式:
class子類:
public父類{};
繼承關(guān)系和訪問限定符
繼承基類成員訪問方式的變化
類成員/繼承方式public繼承protected繼承private繼承基類的public成員派生類的public成員派生類的protected成員派生類的private成員基類的protected成員派生類的protected成員派生類的protected成員派生類的private成員基類的private成員在派生類中不可見在派生類中不可見在派生類中不可見
總結(jié)
基類private成員在派生類中無論以什么方式繼承都是不可見的。這里的不可見是指基類的私有成員還是被繼承到了派生類對(duì)象中,但是語法上限制派生類對(duì)象不管在類里面還是類外面都不能去訪問它?;恜rivate成員在派生類中是不能被訪問,如果基類成員不想在類外直接被訪問,但需要在派生類中能訪問,就定義為protected??梢钥闯霰Wo(hù)成員限定符是因繼承才出現(xiàn)的。實(shí)際上面的表格我們進(jìn)行一下總結(jié)會(huì)發(fā)現(xiàn),基類的私有成員在子類都是不可見?;惖钠渌蓡T在子類的訪問方式==Min(成員在基類的訪問限定符,繼承方式),publicprotectedprivate。使用關(guān)鍵字class時(shí)默認(rèn)的繼承方式是private,使用struct時(shí)默認(rèn)的繼承方式是public,不過最好顯示的寫出繼承方式。在實(shí)際運(yùn)用中一般使用都是public繼承,幾乎很少使用protetced/private繼承,也不提倡使用protetced/private繼承,因?yàn)閜rotetced/private繼承下來的成員都只能在派生類的類里面使用,實(shí)際中擴(kuò)展維護(hù)性不強(qiáng)。
基類和派生類對(duì)象賦值轉(zhuǎn)換
派生類對(duì)象可以賦值給基類的對(duì)象/指針/引用。這里有一個(gè)形象的書法叫做切片或切割
基類對(duì)象不能賦值給派生類對(duì)象
基類的指針可以通過強(qiáng)制類型轉(zhuǎn)換賦值給派生類的指針。但是必須是基類的指針是指向派生類對(duì)象時(shí)才是安全地。
繼承中的作用域
在繼承體系中基類和派生類都有獨(dú)立的作用域。
子類和父類中有同名成員;子類成員將屏蔽父類對(duì)同名成員的直接訪問,這種情況叫做隱藏,也叫作重定義。如果要訪問父類的成員可以使用域作用限定符進(jìn)行訪問。
注意函數(shù)構(gòu)成隱藏的話只需要函數(shù)名相同。
實(shí)際在繼承體系里面最好不要定義同名的成員。
派生類的默認(rèn)成員函數(shù)
在這里又把類與對(duì)象中學(xué)的六個(gè)默認(rèn)成員函數(shù)拉出來了,那么在繼承體系中這幾個(gè)成員函數(shù)是如何生成的呢?
構(gòu)造函數(shù):派生類的構(gòu)造函數(shù)必須基類的構(gòu)造函數(shù)初始化基類的那部分成員。如果基類沒有默認(rèn)的構(gòu)造函數(shù),則必須在派生類構(gòu)造函數(shù)的初始化列表階段顯示調(diào)用。拷貝構(gòu)造函數(shù):派生類的拷貝構(gòu)造函數(shù)必須調(diào)用基類的拷貝構(gòu)造完成基類的拷貝初始化。賦值重載:派生類operator=必須要調(diào)用基類的operator=完成基類的賦值。析構(gòu)函數(shù):派生類的析構(gòu)函數(shù)會(huì)在被調(diào)用完成后自動(dòng)調(diào)用基類的析構(gòu)函數(shù)清理基類成員。因?yàn)檫@樣才能保證派生類對(duì)象先清理派生類成員再清理基類成員的順序。
派生類對(duì)象初始化先調(diào)用基類構(gòu)造再調(diào)派生類構(gòu)造
派生類對(duì)象析構(gòu)清理先調(diào)用派生類析構(gòu)再調(diào)基類的析構(gòu)。
簡(jiǎn)單的運(yùn)用:
classPerson
public:
Person(constchar*name="zhao")
:_name(name)
cout"父構(gòu)造"endl;
Person(constPersonp)
:_name()
cout"父拷貝構(gòu)造"endl;
Personoperator=(constPersonp)
cout"父賦值重載"endl;
if(this!=p)
_name=;
return*this;
~Person()
cout"父析構(gòu)"endl;
protected:
string_name;
classStudent:publicPerson
public:
Student(constchar*name,intnum)
:Person(name)
,_num(num)
cout"子構(gòu)造"endl;
Student(constStudents)
:Person(s)
,_num(num)
cout"子拷貝構(gòu)造"endl;
Studentoperator=(constStudents)
cout"子賦值重載"endl;
if(this!=s)
//小心這里是隱藏
Person::operator=(s);
_num=s._num;
return*this;
//需要注意在這塊~Student()和~Person()構(gòu)成隱藏,這是由于多態(tài)的一些原因,任何類析構(gòu)函數(shù)名都會(huì)被統(tǒng)一處理為destructor()
~Student()
cout"子析構(gòu)"endl;
//為了保證析構(gòu)時(shí),保持先子再父的后進(jìn)先出的析構(gòu)順序,子類析構(gòu)函數(shù)完成后,會(huì)自動(dòng)去調(diào)用父類的析構(gòu)函數(shù)。
protected:
int_num;
};
繼承與友元
友元關(guān)系不能繼承,也就是說基類友元不是子類的友元。
繼承與靜態(tài)成員
基類定義了static靜態(tài)成員,則整個(gè)繼承體系里面只有一個(gè)這樣的成員,無論派生出多少個(gè)子類,都只有一個(gè)static成員實(shí)例。
classPerson
public:
Person(){++_count;}
protected:
string_name;//姓名
public:
staticint_count;//統(tǒng)計(jì)人的個(gè)數(shù)。
intPerson::_count=0;
classStudent:publicPerson
protected:
int_stuNum;//學(xué)號(hào)
classGraduate:publicStudent
protected:
string_seminarCourse;//研究科目
voidTestPerson()
Students1;
Students2;
Students3;
Graduates4;
cout"人數(shù):"Person::_countendl;
Student::_count=0;
cout"人數(shù):"Person::_countendl;
}
復(fù)雜的菱形繼承及菱形虛擬繼承
單繼承:一個(gè)子類只有一個(gè)直接父類時(shí)稱這個(gè)繼承關(guān)系為單繼承
多繼承:一個(gè)子類有兩個(gè)或以上直接父類時(shí)稱這個(gè)繼承關(guān)系為多繼承
菱形繼承:菱形繼承是多繼承的一種特殊情況。
菱形繼承的問題:從下面的對(duì)象成員模型構(gòu)造,可以看出菱形繼承有數(shù)據(jù)冗余和二義性的問題。在Assistant的對(duì)象中Person成員會(huì)有兩份。
虛擬繼承可以解決菱形繼承的二義性和數(shù)據(jù)冗余的問題。如上面的繼承關(guān)系,在Student和Teacher的繼承Person時(shí)使用虛擬繼承,即可解決問題。需要注意的是,虛擬繼承不要在其他地方去使用
虛擬繼承解決數(shù)據(jù)冗余和二義性的原理為了研究虛擬繼承原理,我們給出了一個(gè)簡(jiǎn)化的菱形繼承繼承體系,再借助內(nèi)存窗口觀察對(duì)象成員的模型。
虛繼承原理
虛繼承實(shí)現(xiàn):
在腰部?jī)蓚€(gè)繼承之前加上關(guān)鍵字vittul,實(shí)現(xiàn)虛繼承。
classAnimal{
public:
int_a;
classTuo:virtualpublicAnimal
public:
int_b;
classSheep:virtualpublicAnimal
public:
int_c;
classSheepTuo:publicB,publicC
public:
int_b;
}
要探究虛繼承如何實(shí)現(xiàn),需要借用VS的開發(fā)人員命令提示工具,在VS2025的工具-命令行-開發(fā)者命令提示中。cd到當(dāng)前項(xiàng)目的目錄,輸入cl/d1reportSingleClassLayout要查看的類名文件名,在這里就是cl/d1reportSingleClassLayoutSheepTuodiamond_Inherit.cpp??梢钥吹疆?dāng)前類內(nèi)存的結(jié)構(gòu)。(編譯后才能查看到內(nèi)存分布)
這個(gè)圖就是內(nèi)存結(jié)構(gòu),可以看到,SheepTuo類中分別繼承了來自Sheep類的vbptr(虛基類指針)和Tuo類的vbptr(虛基類指針)。這個(gè)虛基類指針指向的是一個(gè)虛基類表,可以在圖中看到虛基類表中第一項(xiàng)存儲(chǔ)的是vbptr與本類的偏移地址,也就是繼承過來的Sheep類中初始位置就是存放Sheep類的的vbptr,在這里為0;第二項(xiàng)是本類的vbptr與虛基類的公有成員之間的偏移量,也就是Sheep的vbptr和Animal類的age之間偏移為8,Tuo的vbptr和age之間偏移量為4。對(duì)于虛基類的派生類,虛基類的偏移量由實(shí)際類型決定,因此在運(yùn)行時(shí)才可以確定虛基類的地址。
指的注意的是,Sheep類中也是存放了一份age,在這里還可以看到,Sheep和Tuo的Size都是8,因?yàn)槌死^承的age以外,還有Size為4的虛函數(shù)指針
因?yàn)閏lassSheepTuo:publicSheep,publicTuo繼承的時(shí)候,把Sheep和Tuo的vbptr都繼承了,然后通過他們類距離虛基類中的公共成員age的偏移量發(fā)現(xiàn)他們指向的是同一個(gè)age,所以就不會(huì)拷貝兩份,SheepTuo只保留一份age。至于虛繼承底層實(shí)現(xiàn)原理則與編譯器相關(guān)
繼承的總結(jié)
很多人說C++語法復(fù)雜,其實(shí)多繼承就是一個(gè)體現(xiàn)。有了多繼承,就存在菱形繼承,有了菱形繼承就有菱形虛擬繼承,底層實(shí)現(xiàn)就很復(fù)雜。所以一般不建議設(shè)計(jì)出多繼承,一定不要設(shè)計(jì)出菱形繼承。否則在復(fù)雜度及性能上都有問題。
多繼承可以認(rèn)為是C++的缺陷之一,很多后來的OO語言都沒有多繼承,如Java
繼承和組合
public繼承是一種is-a的關(guān)系。也就是說每個(gè)派生類對(duì)象都是一個(gè)基類對(duì)象。
組合是一種has-a的關(guān)系。假設(shè)B組合了A,每個(gè)B對(duì)象中都有一個(gè)A對(duì)象。
優(yōu)先使用對(duì)象組合,而不是類繼承。
繼承允許你根據(jù)基類的實(shí)現(xiàn)來定義派生類的實(shí)現(xiàn)。這種通過生成派生類的復(fù)用通常被稱為白箱復(fù)用(white-boxreuse)。術(shù)語白箱是相對(duì)可視性而言:在繼承方式中,基類的內(nèi)部細(xì)節(jié)對(duì)子類可見。繼承一定程度破壞了基類的封裝,基類的改變,對(duì)派生類有很大的影響。派生類和基類間的依賴關(guān)系很
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年智能建筑系統(tǒng)集成節(jié)能降耗技術(shù)實(shí)施效果評(píng)價(jià)
- 2025年教育信息化2.0對(duì)高校教師教學(xué)管理的影響報(bào)告
- 西方政治制度與智庫的互動(dòng)影響研究試題及答案
- 昭通市彝良縣公安局警務(wù)輔助人員招聘考試真題2024
- 西方政治中的法律與道德試題及答案
- 網(wǎng)絡(luò)流量監(jiān)控工具試題及答案
- 西方媒體與政治的關(guān)系分析試題及答案
- 康復(fù)醫(yī)療服務(wù)體系在康復(fù)醫(yī)療市場(chǎng)中的市場(chǎng)細(xì)分與消費(fèi)者行為分析報(bào)告
- 各國(guó)西方政治制度比較試題及答案
- 新零售時(shí)代2025年數(shù)字化供應(yīng)鏈協(xié)同優(yōu)化路徑探索報(bào)告
- 2024年河北省中考道德與法治真題含解析
- 辦公用品供應(yīng)合同模板
- DLT 5285-2018 輸變電工程架空導(dǎo)線(800mm以下)及地線液壓壓接工藝規(guī)程
- 軍事訓(xùn)練夏令營(yíng)合同樣本
- 2024年國(guó)家保安員資格考試題庫及參考答案(完整版)
- 2023-2024學(xué)年江蘇省連云港市新海實(shí)驗(yàn)中學(xué)英語七年級(jí)第二學(xué)期期末達(dá)標(biāo)檢測(cè)試題含答案
- 2024年南昌市高三二模(第二次模擬測(cè)試)物理試卷(含答案)
- 基礎(chǔ)有機(jī)化學(xué)實(shí)驗(yàn)智慧樹知到期末考試答案2024年
- 項(xiàng)目攻關(guān)方案
- 2024年北京控股集團(tuán)有限公司招聘筆試參考題庫含答案解析
- 勞動(dòng)創(chuàng)造幸福主題班會(huì)
評(píng)論
0/150
提交評(píng)論