版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第 12 章 繼承和派生12.1 繼承的基本概念 12.2 單一繼承 12.3 多重繼承 12.4 基類成員的初始化 12.5 二義性和支配規(guī)則 12.6 虛基類 12.7 訪問基類成員和訪問對象成員的成員 12.8 賦值兼容 第 12 章 繼承和派生 繼承提供了在已有類的基礎(chǔ)上開發(fā)出新類的機制,可以節(jié)省重復代碼的編寫工作,是軟件重用的基礎(chǔ)。 B AA派生類是對基類的擴充12.1 繼承的基本概念已知一個類A,對A類加以擴展,即增加一些屬性和行為,構(gòu)成一個新類B,此時B類將A類已有的屬性和行為繼承下來。稱類 B 繼承了 A ,或稱類 A 派生了 B 。A :父類,基類 BaseClassB :子
2、類,派生類 DerivedClass在校人員類學生類職工類( 屬性:姓名,年齡,身高 ) 增加屬性: 學號 成績 增加屬性: 部門 工資 單一繼承多重繼承圓柱體類 圓類 高度類 組合(屬性: 圓心坐標,半徑) (屬性: 高度)屬性: 圓心坐標,半徑 ,高度在C+中,有兩種繼承方式:單一繼承和多重繼承。 12.2 單一繼承定義派生類的一般格式:class : private: / 私有成員說明 . public: / 公有成員說明 . protected: / 保護成員說明 . ; 繼承方式:public 公有繼承(派生) private 私有繼承(派生) protected 保護繼承(派生)定
3、義派生類新成員12.2.1 公有繼承(派生) A B class A . ;class B: public A / 公有繼承A . ;A 類中的 public 和 protected 成員,在B 中仍然保持其原訪問特性。雖然A中的私有成員也被繼承下來了,但在B中不可直接訪問。A 中的: 在 B 中: 在B的類外(通過對象) private 成員 不可訪問 不可訪問public成員 仍為 public 成員 可訪問protected成員 仍為 protected 成員 不可訪問相當于對B類做如下定義: class B: private: int bx;protected: int ay; int
4、 by;public: int az; int bz; void f1( ).; int Getax( ). void Setax( int x ) ax = x; void f2( ).; float f3( ).;private int ax;例如: 繼承關(guān)系如下:class A private: int ax;protected: int ay;public: int az; void f1( ).; int Getax( )return ax; void Setax( int x ) ax = x; ;class B: public A private: int bx;protecte
5、d: int by;public: int bz; void f2( ).; float f3( ).;藍色斜體是從A類繼承的成員在 B 的成員函數(shù)中可直接訪問A類的ay,az,f1( ),Getax( ),Setax( )相當于對B類做如下定義: class B: private: int bx;protected: int ay; int by;public: int az; int bz; void f1( ).; int Getax( ). void Setax( int x ) ax = x; void f2( ).; float f3( ).;private int ax;例如:
6、繼承關(guān)系如下:class A private: int ax;protected: int ay;public: int az; void f1( ).; int Getax( )return ax; void Setax( int x ) ax = x; ;class B: public A private: int bx;protected: int by;public: int bz; void f2( ).; float f3( ).;在B類中不可直接訪問A類的成員ax可通過 Getax( )、Setax( )訪問A類的私有成員 ax 的值注意:在main( )函數(shù)中,只定義一個Cir
7、cle類對象:int main( )Circle c(0, 0, 2);c.ShowCircle( );c.Move(2, 2);c.ShowCircle( );c.Setxy(0, 0); /重新置圓心坐標 c.Setr(1); /重新置半徑值c.ShowCircle( );return 0; 使用一個Circle類對象 c 時,感覺Circle類是一個完整的類,就象 Point 類不存在一樣。 如Setxy( ) 函數(shù),它是在基類中被定義的,現(xiàn)在它就是Circle類的成員了,但在Circle類中并沒有寫出它的實現(xiàn)函數(shù),代碼是被繼承下來的。例12.1見 “第12章 繼承和派生(例子).doc
8、x” 面向?qū)ο蟪绦蛟O(shè)計中繼承性的優(yōu)點就在于此,系統(tǒng)提供了相當多的已定義好的基類,用戶可以根據(jù)具體的應(yīng)用,在已有類的基礎(chǔ)上構(gòu)架新類,在派生類中,可以直接使用父類部分的代碼,但卻不需要重新編寫父類的代碼。這樣可以加速軟件開發(fā)的速度,保障軟件開發(fā)的質(zhì)量。繼承性是軟件重用的基礎(chǔ)。 在一個類上僅構(gòu)架一個新類,意義并不大。但如果構(gòu)架多個新類,那么就可以減少大量相同代碼的重復編寫工作。如從一個“點”類可以派生出“線”類、“圓”類、“長方形”類等。 從本例中,還可以看出另一個問題:為了實現(xiàn)數(shù)據(jù)保護,在基類中將 x, y 定義為私有成員,但是帶來一個問題,即在派生類中需通過公有成員函數(shù)Getx( ) ,Setx
9、y(x1, y1) 等來訪為基類的私有成員。 如果在基類中將 x, y 定義為保護成員,則公有繼承后,在派生類中x, y 仍然是保護成員,在派生類內(nèi)可直接訪問。這樣既可以保護基類數(shù)據(jù)成員,又可以在派生類中提供訪問基類數(shù)據(jù)成員的方便性。12.2.2 私有繼承(派生) A B class A . ;class B: private A / 私有繼承A . 將 A 中的 public 和 protected 成員均變成了B 的 private 成員。同理,A中的私有成員被繼承下來了,但在B中不可直接訪問,A 中的: 在 B 中: 在類外(類B的對象中) private 成員 不可訪問 不可訪問pub
10、lic成員 變?yōu)?private 成員 不可訪問protected成員 變?yōu)?private 成員 不可訪問相當于對B類做如下定義: class B: private: int bx; int ay; int az; void f1( ).; int Getax( ). void Setax( int x ) ax = x; protected: int by;public: int bz; void f2( ).; float f3( ).;private int ax;例如: 繼承關(guān)系如下:class A private: int ax;protected: int ay;public:
11、int az; void f1( ).; int Getax( )return ax; void Setax( int x ) ax = x; ;class B: private A private: int bx;protected: int by;public: int bz; void f2( ).; float f3( ).;藍色斜體是從A類繼承的成員在 B 的成員函數(shù)中可直接訪問A類的ay,az,f1( ),Getax( ),Setax( )相當于對B類做如下定義: class B: private: int bx; int ay; int az; void f1( ).; int
12、Getax( ). void Setax( int x ) ax = x; protected: int by;public: int bz; void f2( ).; float f3( ).;private int ax;例如: 繼承關(guān)系如下:class A private: int ax;protected: int ay;public: int az; void f1( ).; int Getax( )return ax; void Setax( int x ) ax = x; ;class B: private A private: int bx;protected: int by;
13、public: int bz; void f2( ).; float f3( ).;在B類中不可直接訪問A類的成員ax可通過 Getax( )、Setax( )訪問A類的私有成員 ax 的值12.2.3 保護繼承(派生) A B class A . ;class B: protected A / 保護繼承A . A 中的: 在 B 中: 在類外(類B的對象中) private 成員 不可訪問 不可訪問public成員 變?yōu)?protected 成員 不可訪問protected成員 變?yōu)?protected成員 不可訪問將 A 中的 public 和 protected 成員均變成了B 的 pr
14、otected 成員。同理,A中的私有成員被繼承下來了,但在B中不可直接訪問,由于“私有繼承” 和“保護繼承”用得不多,在這里不再詳細敘述了。 無論何種繼承方式,private成員是無法在派生類中被直接訪問的。而對于protected成員,根據(jù)不同的派生方式,protected成員的直接訪問特性可以被(或不被)傳遞到派生類的派生類中。 12.2.4 private成員和protected成員的區(qū)別 1對于公有派生,基類的protected成員在派生類中依然保持protected屬性。2對于私有派生,基類的protected成員在派生類中變成了private成員,此時基類的protected成員
15、就再也無法在派生類的派生類中被直接訪問了。在繼承或派生鏈中,一旦出現(xiàn)私有繼承,則父類的成員的“類內(nèi)直接訪問特性”就無法在后面的派生中傳遞下去。3對于保護派生,基類的protected成員在派生類中依然保持protected屬性,此時情況與公有派生類似。類中protected成員的優(yōu)點是:既可以在本類中實現(xiàn)數(shù)據(jù)的隱藏(在類外不可被直接訪問),又可以將其類內(nèi)直接訪問特性傳遞到派生類中(在派生類中可直接訪問)。但private成員只能實現(xiàn)本類中的數(shù)據(jù)隱藏,而不能將其類內(nèi)直接訪問特性傳遞到派生類中。 12.3 多重繼承一般格式:class : , , /以下定義派生類新成員 private: / 私有
16、成員說明 . public: / 公有成員說明 . protected: / 保護成員說明 . ;多個基類派生一個類多重繼承Circle 類Point類 Radius類 組合再次說明保護成員的優(yōu)點例12.2 見 “第12章 繼承和派生(例子).docx”注意例12.2的D行,若一個類是由多個基類派生出來的,則在定義派生類構(gòu)造函數(shù)時,應(yīng)調(diào)用基類的構(gòu)造函數(shù),以初始化基類成員。 12.4 基類成員的初始化12.4.1 基類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序 派生類構(gòu)造函數(shù)的一般格式:ClassName : ClassName(args) : Base1(arg1) , Base2(arg2) , . B
17、asen(argn) ;其中ClassName是派生類名,Base1、Base2、.Basen為基類的類名。args是派生類自身的構(gòu)造函數(shù)的形參列表,arg1、arg2、.argn是調(diào)用基類構(gòu)造函數(shù)的實參列表。 析構(gòu)函數(shù)的調(diào)用順序為:(相反)先執(zhí)行派生類自身的析構(gòu)函數(shù)體、然后按 Basen( ) 、.Base2( ) 、Base1( )例12.3 見 “第12章 繼承和派生(例子).docx”構(gòu)造函數(shù)的調(diào)用順序為: Base1( )、 Base2( )、. Basen( )、最后執(zhí)行。 在例12.3中:調(diào)用基類的構(gòu)造函數(shù)的順序并不是B行的書寫順序決定的,而是A行定義派生類時的派生順序決定的,即
18、使將B行改寫成Derived(int x, int y, int z) : Base2(y), Base1(x),程序的運行結(jié)果依然不變。 12.4.2 對象成員構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序 例12.4 見 “第12章 繼承和派生(例子).docx”或見下一頁簡化例子:若派生類中包含對象成員,則在派生類的構(gòu)造函數(shù)的初始化成員列表中:不僅要列舉基類的構(gòu)造函數(shù),而且要列舉對象成員的構(gòu)造函數(shù)class Base1 int data1;public: Base1(int a)data1=a; .;class Base2 int data2; public: Base2(int a)data2=a; .
19、 ;class Derived: public Base1, public Base2 /公有繼承基類 int d; Base1 b1, b2; /對象成員public: Derived(int a, int b):Base1(a), Base2(20),b1(200),b2(a+b) d=a; .先調(diào)用基類的構(gòu)造函數(shù)再調(diào)用對象成員的構(gòu)造函數(shù)最后執(zhí)行對象自身的構(gòu)造函數(shù)問題見下頁問題:對本例,一個Derived類的對象有幾個數(shù)據(jù)成員?(包括自身具備的、和繼承來的? )返回12.5 二義性和支配規(guī)則12.5.1 二義性(多重繼承帶來的訪問沖突)例12.5class A protected: int
20、 x;public: A(int a) x=a; .;class B protected: int x;public: B(int a) x=a; .;class C: public A, public B /公有繼承 A 和 B int y;public: void Setx(int a) x=a; .;當基類 A和 B 中出現(xiàn)兩個同名的成員 x 時,在派生類中訪問 x 出現(xiàn)二義性問題:一個類C的對象有幾個數(shù)據(jù)成員?class A protected: int x;public: A(int a) x=a; .;class B protected: int x;public: B(int a
21、) x=a; .;class C: public A, public B /公有繼承 A 和 B int y;public: void Setx(int a) x=a; .;解決辦法:將此句改為:A:x = a; 或 B:x = a;同理:解決基類同名成員函數(shù)的訪問class C: public A, public B /公有繼承 A 和 Bint y;public:void SetAx(int a) A:x=a;/對類A中的x置值void SetBx(int a) B:x=a;/對類B中的x置值void Sety(int b) y=b; int Gety( ) return y; ;int
22、main( )C c1;c1.SetAx(35);c1.SetBx(45);c1.Sety(300);coutY=c1.Gety( )endl;return 0;例12.6 部分代碼,解決訪問沖突 C A B 注意:如何解決沖突 (訪問二義性)。當把派生類作為基類,又派生出新的派生類時,這種限定作用域的運算符不能連續(xù)嵌套使用,如下形式的使用方式是不允許的: : : : 例12.7 見 “第12章 繼承和派生(例子).docx”如何解決多層繼承中的沖突,請看下例:由于C+是通過作用域運算符來解決訪問二義性問題,因此規(guī)定任一基類在派生類中只能被直接繼承一次,否則會造成成員名訪問的沖突。例如:cla
23、ss A public: float x; .;class B: public A, public A /錯誤的. ;B類的定義是錯誤的,因為如果直接從A類繼承兩次,通過作用域運算符就無法解決訪問二義性問題。 12.5.2 支配規(guī)則例12.8 支配規(guī)則示例 見 “第12章 繼承和派生(例子).docx”問題:類 C 有幾個數(shù)據(jù)成員?;惡团缮惓霈F(xiàn)同名成員時,派生類成員訪問優(yōu)先-支配規(guī)則12.6 虛基類 類D 基類B 基類C 基類A 基類A 如右圖的公有繼承關(guān)系中, 在類 D 中包含了基類 A 的 兩個拷貝。 在類 D 的成員函數(shù)中, 欲訪問 A 的成員 x , 則必須以 B:x 和 C:x
24、區(qū)分。 B DA C A一個D類對象的存儲空間 若欲使公共的基類A 在派生類中只有一個拷貝, 如右圖, 可將 A 說明成虛基類。 說明的方法: 繼承時,在基類的類名前 加上關(guān)鍵詞:virtual 類D 基類B 基類C 基類A 例12.10 虛基類的例子見下頁: B D C A一個D類對象的存儲空間 class A protected: int x; public: A(int a=0) x=a; ;class B: virtual public A protected: int y; public: B(int a=0, int b=0):A(a) y=b; ;class C: public
25、virtual A protected: int z; public: C(int a=0, int c=0):A(a) z=c; ;注意: virtual 的位置。class D: public B, public C protected: int k; B(a1, b), C(a2, c), k(d) public: D(int a1=0, int a2=0, int b=0, int c=0, int d=0) : void Show( )cout x= x , ; cout y= y , ;cout z= z , ;cout k= k endl;int main(void)D obj(
26、1, 1, 2, 3, 4);obj.Show( );return 0; 發(fā)揮 程序的運行結(jié)果是:x=0, y=2, z=3, k=4問題:類 D 有幾個數(shù)據(jù)成員?B 和 C 的構(gòu)造函數(shù)中,分別調(diào)用 A的構(gòu)造函數(shù),編譯器無法確定調(diào)用哪一個來初始化A,在這種情況下,約定直接調(diào)用 A 的缺省構(gòu)造函數(shù)。(即使 a1 和 a2 的值相等)如將G行改為:D(int a1=0, int a2=0, int b=0, int c=0, int d=0) : B(a1, b), C(a2, c), A(a1), k(d) /G 則程序的運行結(jié)果變?yōu)椋?x=1, y=2, z=3, k=4 注意:如果派生類有多個基類,有些是虛基類有些是非虛基類。則基類構(gòu)造的調(diào)用順序是先調(diào)用虛基類的構(gòu)造函數(shù)再調(diào)用非虛基類的構(gòu)造函數(shù),并按照繼承順序調(diào)用。直接調(diào)用虛基類的構(gòu)造函數(shù)例12.11 見 “第12章 繼承和派生(例子).docx”在成員函數(shù)中:(1) 使用基類的成員 (2) 使用對象成員的成員時,情況不同12.7 訪問基類成員和訪問對象成員的成員class A public: int x; A(int
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 生物課題研究的學生參與計劃
- 經(jīng)理的時間管理技巧分享計劃
- 酒店管理的企業(yè)文化
- 敬業(yè)行業(yè)話務(wù)員崗位展望
- 2025年中考物理一輪復習之聲現(xiàn)象
- 酒店管理的利益最大化
- 物流行業(yè)倉儲配送培訓總結(jié)
- 汽車美容銷售顧問銷售總結(jié)報告
- 2024年設(shè)備監(jiān)理師考試題庫附答案(輕巧奪冠)
- 2024年稅務(wù)師題庫及答案【易錯題】
- 政治-2025年八省適應(yīng)性聯(lián)考模擬演練考試暨2025年四川省新高考教研聯(lián)盟高三年級統(tǒng)一監(jiān)測試題和答案
- 2024年中國醫(yī)藥研發(fā)藍皮書
- 坍塌、垮塌事故專項應(yīng)急預案(3篇)
- 2024年融媒體中心事業(yè)單位考試工作人員另選錄用55人內(nèi)部選題庫及參考答案(研優(yōu)卷)
- 陜西省安康市2023-2024學年高一上學期期末考試 生物 含解析
- WPS Office辦公軟件應(yīng)用教學教案
- 2024年時政熱點知識競賽試卷及答案(共四套)
- 幼兒園后勤主任年終總結(jié)
- 除顫儀使用護理查房
- 初級消防設(shè)施操作員實操題庫 (一)
- CURTIS1232-1234-1236-SE-SERIES交流控制器手冊
評論
0/150
提交評論