版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第五章繼承與派生2023/4/232派生類的引入C++的類提供了良好的模塊分解技術,也具有可重用軟件所期望的品質:它們是相似一致的模塊,通過信息隱藏,將它們的接口和實現清楚地分開來。我們還希望在類的基礎上能取得更好的可重用性和可擴充性的目標。面向對象的繼承技術提供了實現上述目標的有力手段。2023/4/233現實中的繼承與派生在自然界中,繼承這個概念是非常普遍的。例如:小貓仔繼承了貓爸貓媽的特性,所以長的是貓鼻子貓眼,我們不會把它錯認為是小狗。繼承就是將一些本質的特性遺傳給子代,使后代在很大程度上具有與父代相同的性質。子代同時還具有父代沒有的特性。2023/4/234再來看一個現實世界中的例子:RectangleSquareDiamondParallelogramQuadrangle四邊形是一個基本的概念,矩形、正方形、菱形和平行四邊形都是派生的概念,因為它們都屬于四邊形,它們繼承了四邊形的所有性質,同時又擴充出各自的特性。2023/4/235不具有對稱性不是所有植物都屬于蕨類傳遞性
高等植物、蕨類植物、芒萁都是植物,具有植物的共同特征植物
低等植物高等植物藻類菌類地衣類苔蘚類蕨類裸子類被子類地錢小金發(fā)草毛蕨芒萁杉木柏木荔枝橘子再來看一個現實世界中的例子:2023/4/236從上面的例子可以看出:而且子代可以擁有父代沒有的特性,這是可擴充的概念。一旦指定了某種事物父代的本質特征,那么它的子代將會自動具有那些性質。這就是一種樸素的可重用的概念。2023/4/237從軟件設計的角度來看:基于已有的類,可以建立新的類。這個新的類既重用已有類的功能,又擴展了新的功能。類是某類事物共同特性的體現,它對外提供了特定的功能。2023/4/238C++的繼承關系繼承就是在一個已經存在的類的基礎上建立另一個新的類。基類派生類已存在的類稱為“基類”或“父類”,新建立的類稱為“派生類”或“子類”,如圖所示:2023/4/239派生類的功能主要通過以下方式來體現:派生類的特性吸收基類成員添加新成員改造基類成員從編碼的角度來看,派生類從基類中以較低的代價換來了較大的靈活性。一旦產生了可靠的基類,只需要調試派生類中所作的修改即可。派生類可以對繼承的屬性進行擴展、限制或改變。2023/4/2310單繼承和多繼承單繼承:派生類只有一個直接基類ABC單繼承XYZ多繼承多繼承:派生類有多個直接基類2023/4/2311單繼承派生類定義單繼承派生類的語法格式:
class派生類名:<繼承方式>基類名{ ……//派生類新添加的成員 };“繼承方式”可以是public、private、以及protected。雖然繼承了基類的所有成員,但是派生類并非都能訪問基類的所有成員,繼承方式會影響派生類對基類中各種成員的引用。2023/4/2312公有派生類在聲明派生類時將繼承方式指定為public時,該類稱為公有派生類。class派生類名:public基類名
{ ……//派生類新添加的成員};2023/4/23137.2.1訪問控制public成員protected成員private成員public成員protected成員private成員基類派生類2023/4/2314基類的成員在公有派生類中的引用權限基類公有成員私有成員保護成員公有派生類公有成員不可訪問成員保護成員不可訪問成員在類外不能被直接訪問。在派生類的類內不能被直接訪問。2023/4/2315舉例:公有派生classBase{ intv1;public: intv2; Base(inta=0,intb=0){ v1=a;v2=b; }};classDerived:publicBase{ intv3;public: intv4; Derived(inta=0,intb=0){ v3=a;v4=b; } voidfunc(){ intsum1=v1+v2+v3+v4; intsum2=v2+v3+v4; }};voidmain(){ Derivedobj(5,6); obj.v2=8;}//錯誤2023/4/2316私有派生類在聲明派生類時將繼承方式指定為private時,該類稱為私有派生類。class派生類名:private基類名{……//派生類新添加的成員};2023/4/2317基類的成員在私有派生類中的引用權限基類公有成員私有成員保護成員私有派生類私有成員不可訪問成員私有成員2023/4/2318舉例:私有派生classBase{ intv1;public: intv2; Base(inta=0,intb=0){ v1=a;v2=b; }};classDerived:privateBase{ intv3;public: intv4; Derived(inta=0,intb=0){ v3=a;v4=b; } voidfunc(){ intsum1=v1+v2+v3+v4; intsum2=v2+v3+v4; }};voidmain(){ Derivedobj(5,6); obj.v2=8;//錯誤//錯誤2023/4/2319公有派生和私有派生的比較雖然派生類繼承了基類所有的成員,但是基類的私有成員對于派生類來說是不可見的,因此不能被派生類所訪問。基類公有成員私有成員保護成員公有派生類公有成員不可訪問成員保護成員私有派生類私有成員不可訪問成員私有成員2023/4/2320保護成員的引入為了解決這個問題,C++專門設置了保護成員,即用protected關鍵字說明的成員。保護成員的特性:能夠被基類和派生類所訪問。和私有成員一樣,類外不能訪問。2023/4/2321舉例:保護成員classBase{protected: intv1;public: intv2; Base(inta=0,intb=0){ v1=a;v2=b; }};classDerived:publicBase{ intv3;public: intv4; Derived(inta=0,intb=0){ v3=a;v4=b; } voidfunc(){ intsum1=v1+v2+v3+v4; intsum2=v2+v3+v4; }};voidmain(){ Derivedobj(5,6); obj.v1=8;}//錯誤//正確2023/4/2322保護派生類在聲明派生類時將繼承方式指定為protected時,該類稱為保護派生類:class派生類名:protected基類名
{……//派生類新添加的成員};2023/4/2323基類的成員在保護派生類中的引用權限基類公有成員私有成員保護成員保護派生類保護成員不可訪問成員保護成員2023/4/2324小結不同的繼承方式,子類對基類中的成員的訪問權限如下表所示:基類公有成員私有成員保護成員公有派生類公有成員不可訪問成員保護成員保護派生類保護成員不可訪問成員保護成員私有派生類私有成員不可訪問成員私有成員2023/4/2325派生類與基類同名成員的訪問方式C++允許派生類可以重新定義基類的成員,此時稱派生類的成員覆蓋了基類的同名成員。如果在派生類中,想使用基類的同名成員,則可以顯式地使用類名+限定符的方式,如下所示:基類名::成員2023/4/2326舉例classBase{protected: intv1;public: intv2; Base(inta=0,intb=0){ v1=a;v2=b; }};classDerived:publicBase{ intv2;public: intv3; Derived(inta=0,intb=0){ v2=a;v3=b; } voidfunc(){
intsum1=v1+v2+v3;
intsum2=v1+Base::v2+v3; }};voidmain(){ Derivedobj(5,6); obj.v2=8;}//錯誤 obj.Base::v2=9;//使用的是Derived中的v2//使用的是Base中的v22023/4/2327派生類對象的構造和析構派生類對象數據成員的構成:從基類繼承過來的數據成員派生類自定義的數據成員如何初始化這幾部分數據成員呢?基本數據類型類類型如何析構派生類對象?2023/4/2328單繼承派生類的構造函數派生類構造函數(參數表):基類構造函數(參數表),對象成員1(參數表),
…… 對象成員n(參數表),{
……//初始化自定義數據成員}如果基類使用的是缺省的構造函數或不帶參數的構造函數,那么在初始化列表中可以省略“基類構造函數(參數表)“這一項。如果沒有對象成員,那么在初始化列表中可以省略“對象成員(參數表)“這一項。2023/4/2329構造函數的調用順序如下:構造函數和析構函數的調用順序先調用基類構造函數;再調用對象成員所屬類的構造函數;最后調用派生類構造函數;析構函數的調用順序如下:再調用對象成員所屬類的析構函數;先調用派生類的析構函數;最后調用基類的析構函數;2023/4/2330舉例classBase{public:Base(){cout<<“Basecreated\n”;}};classDerived:publicBase{public:Derived(){cout<<“Derivedcreated\n”;}};voidmain(){ Derivedd;}2023/4/2331請分析classbase{ intx;public: base(inti):x(i){ cout<<"base\n"; }};classderived:publicbase{ inta;public: derived(inti):a(i*4),base(a){ cout<<"derived\n"; }};此時基類的數據成員x的值為多少?2023/4/2332賦值兼容規(guī)則在公有派生方式下,派生類對象可以作為基類對象來使用,具體方式如下:以上規(guī)則的具體使用方式:派生類的對象可以直接賦值給基類的對象基類對象的引用可以引用一個派生類對象基類對象的指針可以指向一個派生類對象BaseBobj;DerivedDobj;Bobj=Dobj;Base&refB=Dobj;Base*pB=&Dobj;2023/4/2333需要思考的兩個問題為什么是“派生類對象->基類對象”,而不是“基類對象->派生類對象”?其他繼承方式會有以上規(guī)則嗎?2023/4/2334解決第一個問題v1v2v1v2v3v4基類對象派生類對象基類對象和派生類對象的內存布局方式當一個派生類對象直接賦值給基類對象時,不是所有的數據都賦給了基類對象,賦予的只是派生類對象的一部分。這部分叫做派生類對象的“切片”(sliced)。2023/4/2335解決第二個問題回憶一下不同的繼承方式,子類對基類中的成員的訪問權限:基類公有成員私有成員保護成員公有派生類公有成員不可訪問成員保護成員私有派生類私有成員不可訪問成員私有成員保護派生類保護成員不可訪問成員保護成員只有在公有派生的情況下,才有可能出現“基類的公有成員變成派生類的公有成員”的情況。2023/4/2336多繼承派生類派生類有多個直接基類,這叫多繼承。QuadrangleDiamondSquareRectangleQuadrangle2023/4/2337定義多繼承派生類的語法格式:class派生類名:<繼承方式1>基類名1, <繼承方式2>基類名2,
……{
……//派生類新添加的成員};2023/4/2338多繼承派生類對象的構造和析構多繼承派生類的構造函數:派生類名(參數表):基類名1(參數表1),
基類名2(參數表2),
對象成員1(參數表3), 對象成員2(參數表4),
…{ //派生類新添加的成員}2023/4/2339派生類構造函數的執(zhí)行順序:先執(zhí)行所有基類的構造函數(按這些基類被繼承時聲明順序依次執(zhí)行基類1、基類2的構造函數)。最后執(zhí)行派生類本身的構造函數。再執(zhí)行對象成員所屬類的構造函數(按照這些對象成員在類中定義的順序)。2023/4/2340多繼承中的二義性問題在多繼承中,一個類不可以重復成為另一個類的直接基類,但可以多次成為間接基類。此時派生類訪問基類成員時可能出現二義性。訪問共同基類的成員時可能出現二義性。訪問不同基類的具有相同名字成員時可能出現二義性。2023/4/2341訪問不同基類同名成員時的二義性
classA{public:
intvalue;voidf();};classB{public:intvalue;voidf();voidg();};classC:publicA,publicB{public:voidg();voidh();};voidmain(){CC1;
C1.f();
C1.value=9;}//出現二義性//出現二義性解決辦法是用類名對成員加以限定,例如:
C1.A::f();或者C1.B::f(); C1.A::value=9;或者C1.B::value=9;2023/4/2342訪問共同基類成員時的二義性
classA{ public: inta; voidg();};classB1:publicA{ intb1;};classB2:publicA{ intb2;};classC:publicB1,publicB2{ intc;public:intf();};voidmain(){CCobj;Cobj.a=8;Cobj.A::a=9;
Cobj.g();}//出現二義性//出現二義性//出現二義性解決辦法:Cobj.B1::a=9;或Cobj.B2::a=9;2023/4/2343以上類的關系如下圖所示:A(a,g())B1(b1)A(a,g())B2(b2)C(f(),c)類A是派生類C兩條繼承路徑上的一個公共基類,因此這個公共基類會在派生類對象中產生兩個基類子對象。雖然可以通過類限定符的方式避免二義性,但問題的關鍵在于我們不需要在派生類對象中存在多個基類對象的拷貝!如果要使這個公共基類在派生類中只產生一個基類子對象,則需要將這個基類設置為虛基類。2023/4/2344虛基類引進虛基類的目的是為了解決二義性問題,使公共基類在其派生類對象中只產生一個基類子對象。虛基類說明格式如下:
virtual<繼承方式><基類名>在“繼承方式”前面用關鍵字virtual來說明2023/4/2345例子:虛基類的使用
classA{ public: inta; voidg();};classB1:virturalpublicA{ intb1;};classB2:virturalpublicA{ intb2;};classC:publicB1,publicB2{ intc;public:intf();};voidmain(){CCobj;Cobj.a=8;//或Cobj.A::a=9;Cobj.g();}2023/4/2346A(g(),a)B1(b1)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國雙聯二三極連體插座數據監(jiān)測研究報告
- 2025至2030年天鈣元項目投資價值分析報告
- 2025至2030年乙萘酚項目投資價值分析報告
- 2025至2030年醋酸膠布項目投資價值分析報告
- 2025至2030年純正特香菜籽油項目投資價值分析報告
- 2025至2030年旅游枕套項目投資價值分析報告
- 二零二五年度煤炭產品委托銷售合同書
- 二零二五年度文化用品銷售提成與品牌授權合同
- 二零二五年度海外院校學分轉換合同協(xié)議范本4篇
- 2025年昆山物業(yè)費調價與新服務升級全面合同3篇
- 2025-2030年中國陶瓷電容器行業(yè)運營狀況與發(fā)展前景分析報告
- 二零二五年倉儲配送中心物業(yè)管理與優(yōu)化升級合同3篇
- 2025屆廈門高三1月質檢期末聯考數學答案
- 音樂作品錄制許可
- 江蘇省無錫市2023-2024學年高三上學期期終教學質量調研測試語文試題(解析版)
- 拉薩市2025屆高三第一次聯考(一模)英語試卷(含答案解析)
- 開題報告:AIGC背景下大學英語教學設計重構研究
- 師德標兵先進事跡材料師德標兵個人主要事跡
- 連鎖商務酒店述職報告
- 《實踐論》(原文)毛澤東
- 第三單元名著導讀《紅星照耀中國》(公開課一等獎創(chuàng)新教學設計+說課稿)
評論
0/150
提交評論