C程序設(shè)計(jì)課件:第17章 多重繼承_第1頁(yè)
C程序設(shè)計(jì)課件:第17章 多重繼承_第2頁(yè)
C程序設(shè)計(jì)課件:第17章 多重繼承_第3頁(yè)
C程序設(shè)計(jì)課件:第17章 多重繼承_第4頁(yè)
C程序設(shè)計(jì)課件:第17章 多重繼承_第5頁(yè)
已閱讀5頁(yè),還剩35頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、第17章 多重繼承本章主要內(nèi)容 17.1 多繼承如何工作 17.2 繼承的模糊性 17.3 虛擬繼承 17.4 多繼承的構(gòu)造順序 17.5 繼承的訪(fǎng)問(wèn)控制 17.6 保護(hù)繼承與私有繼承 作業(yè)217.1多繼承如何工作 多重繼承即多繼承:由多個(gè)基類(lèi)派生而成新的類(lèi) 例如,兩用沙發(fā),它是一個(gè)沙發(fā),也是一張床,兩用沙發(fā)應(yīng)允許同時(shí)繼承沙發(fā)和床的特性,即SleeperSofa類(lèi)繼承Bed和Sofa兩個(gè)類(lèi)。3Sleep()SetWeight()BedWeightWatchTv()SetWeight()SofaWeightFoldOut()SleeperSofa床和沙發(fā)的分解4/* ch17_1.cpp *#i

2、ncludeclass Bed public: Bed() :weight(0) void Sleep() coutSleeping.n; void SetWeight(int i) weight =i; protected: int weight;class Sofa public: Sofa() :weight(0) void WatchTV() cout Watching TV.n; void SetWeight(int i) weight =i; protected: int weight;5class SleeperSofa :public Bed, public Sofa publ

3、ic: SleeperSofa() void FoldOut() /折疊與打開(kāi) coutFold out the sofa.n; ;int main() SleeperSofa ss; ss.WatchTV(); ss.FoldOut(); ss.Sleep();運(yùn)行結(jié)果:Watching TV.Fold out the sofa.Sleeping617.2 繼承的模糊性 模糊性:二義性二義性:對(duì)某個(gè)成員訪(fǎng)問(wèn)不能唯一確定二義性產(chǎn)生的原因:不同類(lèi)的成員可以同名規(guī)定:在多繼承、多層次的繼承結(jié)構(gòu)中,總是逐層往上、訪(fǎng)問(wèn)最靠近自己的那個(gè)同名成員。但是,如果在同一層的兩個(gè)類(lèi)中具有同名成員,則產(chǎn)生二義性。

4、7int main() sleepersofa ss; ss.SetWeight(20); /error /是Bed的SetWeight還是sofa的SetWeight?這導(dǎo)致了名稱(chēng)沖突,在編譯時(shí)將予以拒絕。程序必須在重量面前說(shuō)明基類(lèi)int main() sleepersofa ss; ss.Sofa:SetWeight(20); /說(shuō)明是沙發(fā)重量20斤17.2 繼承的模糊性817.2 繼承的模糊性 二義性解決辦法: 在成員名前用類(lèi)名進(jìn)行限定(類(lèi)名:成員名),可以解決同一層的兩個(gè)類(lèi)中具有同名成員而產(chǎn)生的二義性。 虛基類(lèi)(即虛擬繼承),可以解決上述訪(fǎng)問(wèn)同一個(gè)基類(lèi)的成員,但存在多條路徑的問(wèn)題。91

5、7.3 虛擬繼承 從意義上來(lái)看,一個(gè)SleepSofa沒(méi)有沙發(fā)和床兩種重量,如此的繼承不是真實(shí)的現(xiàn)實(shí)世界描述。進(jìn)一步分析可得,床和沙發(fā)都是家具的一種,凡家具都有重量,所以通過(guò)分解來(lái)考察其關(guān)系。10GetWeight()SetWeight()FurnitureWeightGetWeight()SetWeight()FurnitureWeightSleep()BedWatchTv()SofaFoldOut()SleeperSofa沙發(fā)床的分解11/* ch17_2.cpp *#includeclass Furniture public: Furniture() void SetWeight(int

6、 i) weight =i; int GetWeight() return weight; protected: int weight;class Bed :public Furniture public: Bed() void Sleep() cout Sleeping.n; ;12class Sofa :public Furniture public: Sofa() void WatchTV() cout Watching TV.n; ;class SleeperSofa :public Bed, public Sofa public: SleeperSofa() :Sofa(), Bed

7、() void FoldOut() cout Fold out the sofa.n; ;int main() SleeperSofa ss; ss.SetWeight(20); /編譯出錯(cuò)!模糊的SetWeight成員 Furniture* pF; pF=(Furniture*)&ss; /編譯出錯(cuò)!模糊的Furniture* cout GetWeight() endl;13GetWeight()SetWeight()FurnitureWeightGetWeight()SetWeight()FurnitureWeightSleep()BedWatchTv()SofaFoldOut()Slee

8、perSofaSleeperSofa的實(shí)際繼承關(guān)系14Furniture weightBed繼承部分 Furniture weightSofa繼承部分SleepSofa繼承部分床部分沙發(fā)部分SleepSofa完整對(duì)象完整的SleeperSofa對(duì)象內(nèi)存布局1517.3 虛擬繼承 虛擬繼承的概念: 在多條繼承路徑上存在一個(gè)公共的基類(lèi),在這些路徑的匯合處(某個(gè)派生類(lèi))就產(chǎn)生這個(gè)公共基類(lèi)的多個(gè)“副本”。如果只希望存在一個(gè)副本,可以把此公共基類(lèi)聲明為虛基類(lèi)(虛擬繼承)。 虛擬繼承的方法: 虛基類(lèi)是對(duì)派生類(lèi)而言,所以,虛基類(lèi)本身的定義不變,在定義派生類(lèi)時(shí)聲明該基類(lèi)為虛基類(lèi)即可(冠以關(guān)鍵字:virtual

9、)。 16/* ch17_3.cpp *#includeclass Furniture public: Furniture() void SetWeight(int i) weight =i; int GetWeight() return weight; protected: int weight;class Bed :virtual public Furniture public: Bed() void Sleep() cout Sleeping.n; ;17class Sofa :virtual public Furniture public: Sofa() void WatchTV()

10、cout Watching TV.n; ;class SleeperSofa :public Bed, public Sofa public: SleeperSofa() :Sofa(), Bed() void FoldOut() cout Fold out the sofa.n; ;int main() SleeperSofa ss; ss.SetWeight(20); cout ss.GetWeight() endl;運(yùn)行結(jié)果: 20 18 Furniture weightBed繼承部分Sofa繼承部分SleeperSofa部分虛擬繼承的完整SleeperSofa對(duì)象虛擬繼承的Sleepe

11、rSofa內(nèi)存布局虛擬繼承的虛擬和虛擬函數(shù)的虛擬沒(méi)有任何關(guān)系!1917.4 多繼承的構(gòu)造順序派生類(lèi)的構(gòu)造函數(shù)調(diào)用次序(調(diào)用原則):1. 先基類(lèi),再成員,后自己。2. 在同一層上如有多個(gè)基類(lèi),則先虛基類(lèi),后非虛基類(lèi)。3. 在同一層上如有多個(gè)虛基類(lèi),則按派生時(shí)定義的先后次序執(zhí)行;在同一層上如有多個(gè)非虛基類(lèi),則按派生時(shí)定義的先后次序執(zhí)行。 4. 對(duì)于一個(gè)派生類(lèi)的某個(gè)虛基類(lèi)的構(gòu)造函數(shù)一旦被執(zhí)行過(guò),就不再被多次執(zhí)行。5. 虛基類(lèi)的派生類(lèi)的構(gòu)造函數(shù)的定義無(wú)特殊規(guī)定。2017.4 多繼承的構(gòu)造順序6. 如果“最后派生類(lèi)”的構(gòu)造函數(shù)的初始化列表中不調(diào)用虛基類(lèi)的構(gòu)造函數(shù),則該派生類(lèi)的虛基類(lèi)的構(gòu)造函數(shù)必須是無(wú)參的

12、,或全部是缺省值的構(gòu)造函數(shù)7. 如果“最后派生類(lèi)”的構(gòu)造函數(shù)的初始化列表中不調(diào)用虛基類(lèi)的構(gòu)造函數(shù),則虛基類(lèi)的初始值采用其構(gòu)造函數(shù)的缺省值;如果“最后派生類(lèi)”的構(gòu)造函數(shù)的初始化列表中調(diào)用了虛基類(lèi)的構(gòu)造函數(shù),并且?guī)氤跏贾?,則虛基類(lèi)的初始值采用帶入的值。21/* ch17_4.cpp *#includeclass OBJ1 public: OBJ1() cout OBJ1n; ;class OBJ2 public: OBJ2() cout OBJ2n; ;class Base1 public: Base1() cout Base1n; ;class Base2 public: Base2() co

13、ut Base2n; ;22class Base3 public: Base3() cout Base3n; ;class Base4 public: Base4() cout Base4n; ;class Derived :public Base1, virtual public Base2, public Base3, virtual public Base4 protected: OBJ1 obj1; OBJ2 obj2; public: Derived() :Base4(), Base3(), Base2(), Base1(), obj2(), obj1() cout Derived

14、ok.n; ;23int main() Derived aa; cout This is ok.n;運(yùn)行結(jié)果: Base2 Base4 Base1 Base3 OBJ1 OBJ2 Derived ok. This is ok. 在語(yǔ)言中實(shí)現(xiàn)多重繼承并不容易,這主要是編譯程序問(wèn)題,還有模糊性問(wèn)題。建議你如果可能,盡量避免用多重繼承。單個(gè)繼承提供了足夠的功能,不一定非用多重繼承不可。24#includeclass Base1 /虛基類(lèi) private: int a,b; public: Base1(int aa=0,int bb=0) /構(gòu)造函數(shù):是帶缺省值的,或者是無(wú)參數(shù)的 a=aa; b=bb

15、; coutBase1 class!endl; void show()coutBase1: a=a b=bendl; ;class Base2 public: Base2() coutBase2 class!endl; void show2() coutBase2: endl; ;25class Level1: public Base2,virtual public Base1 public: Level1(int a,int b):Base1(a,b) coutLevel1 class!endl; ;class Level2:public Base2,virtual public Base1

16、 /虛基類(lèi) public: Level2(int a,int b):Base1(a,b) coutLevel2 class!endl; ;class Lastlevel: public Level1,virtual public Level2 public: Lastlevel(int a,int b):Level1(a,b), Level2(a,b) /Lastlevel(int a,int b):Level1(a,b), Level2(a,b), Base1(a,b) coutLastlevel class!endl; ;26int main() Lastlevel obj(7,9); o

17、bj.show(); /直接調(diào)用間接基類(lèi)base的公有成員函數(shù)show(),無(wú)二義性 /obj.show2(); error /訪(fǎng)問(wèn)間接基類(lèi)base2的公有成員函數(shù)show2(),存在二義性 執(zhí)行結(jié)果:Base1 class!Base2 class!Level2 class!Base2 class!Level1 class!Lastlevel class!Base1: a=0 b=0 /Base1: a=7 b=9 2717.5 繼承類(lèi)別及其訪(fǎng)問(wèn)控制繼承方式基類(lèi)成員特性基類(lèi)中的成員在派生類(lèi)中的特性公有繼承(public)publicpublicprotectedprotectedprivate

18、不可訪(fǎng)問(wèn)私有繼承(private)publicprivateprotectedprivateprivate不可訪(fǎng)問(wèn)保護(hù)繼承(protected)publicprotectedprotectedprotectedprivate不可訪(fǎng)問(wèn)2817.5 繼承類(lèi)別及其訪(fǎng)問(wèn)控制公有成員:一個(gè)類(lèi)的公有成員允許本類(lèi)的成員函數(shù)、本類(lèi)的對(duì)象、公有派生類(lèi)的成員函數(shù)、公有派生類(lèi)的對(duì)象訪(fǎng)問(wèn)。私有成員:一個(gè)類(lèi)的私有成員只允許本類(lèi)的成員函數(shù)訪(fǎng)問(wèn)。保護(hù)成員:具有私有成員和公有成員的特性,對(duì)其派生類(lèi)而言是公有成員,對(duì)其對(duì)象而言是私有成員。2917.5 繼承類(lèi)別及其訪(fǎng)問(wèn)控制公有繼承:基類(lèi)的公有段成員被繼承為公有的,基類(lèi)的保護(hù)段成

19、員被繼承為保護(hù)的。派生時(shí)用“public”作訪(fǎng)問(wèn)控制。私有繼承:基類(lèi)的公有段成員被繼承為私有的,基類(lèi)的保護(hù)段成員被繼承為私有的,派生時(shí)用“private”作訪(fǎng)問(wèn)控制。保護(hù)繼承:基類(lèi)的公有段成員被繼承為保護(hù)的,基類(lèi)的保護(hù)段成員被繼承為保護(hù)的,派生時(shí)用“protected”作訪(fǎng)問(wèn)控制。30class Base public: int m1; protected: int m2; private: int m3;class PrivateClass:private Base /私有繼承 public: void test() m1=1; /ok:將m1據(jù)為private m2=2; / ok:將m2

20、據(jù)為private m3=3; /不可訪(fǎng)問(wèn) ;31class DerivedFromPri:public PrivateClass public: void test() m1=1; /不可訪(fǎng)問(wèn)基類(lèi)的私有成員 m2=2; /不可訪(fǎng)問(wèn) m3=3; /不可訪(fǎng)問(wèn) ;class ProtectedClass:protected Base /保護(hù)繼承 public: void test() m1=1; /m1據(jù)為protected m2=2; /m2據(jù)為protected m3=3; /不可訪(fǎng)問(wèn) ;32class DerivedFromPro:public ProtectedClass public:

21、void test() m1=1; /m1為protected m2=2; /m2仍為protected m3=3; /不可訪(fǎng)問(wèn) ;class PublicClass:public Base /公共繼承 public: void test() m1=1; /m1為public m2=2; /m2為protected m3=3; /不可訪(fǎng)問(wèn) ; 33class DerivedFromPub:public PublicClass public: void test() m1=1; /m1仍保持為public m2=2; /m2仍保持為protected m3=3; /不可訪(fǎng)問(wèn) ;int main(

22、) PrivatedClass priObj1; priObj1.m1=1; /error priObj1.m2=2; /error priObj1.m3=3; /error ProtectedClass proObj2; priObj2.m1=1; /error priObj2.m2=2; /error priObj2.m3=3; /error PublicClass pubObj3; priObj3.m1=1; /ok priObj3.m2=2; /error priObj3.m3=3 /error3417.5 繼承類(lèi)別及其訪(fǎng)問(wèn)控制 私有繼承時(shí),基類(lèi)中不管是公有還是保護(hù)的成員,在子類(lèi)中一律

23、變成私有成員。保護(hù)繼承時(shí),基類(lèi)中公共和保護(hù)的成員在子類(lèi)中變成保護(hù)的。公共繼承時(shí),基類(lèi)中為公共、保護(hù)的成員在子類(lèi)中仍保持為公共、保護(hù)的。在繼承關(guān)系中,基類(lèi)的private成員不但對(duì)應(yīng)用程序隱藏,對(duì)派生類(lèi)也隱藏。而基類(lèi)的保護(hù)成員則只對(duì)應(yīng)用程序隱藏,而對(duì)派生類(lèi)則毫不隱瞞。 3517.6 保護(hù)繼承與私有繼承一個(gè)私有的或保護(hù)的派生類(lèi)不是子類(lèi),因?yàn)榉枪械呐缮?lèi)不能做基類(lèi)能做的所有的事情,但有與基類(lèi)相似的行為。例如,下面的代碼定義了一個(gè)私有繼承基類(lèi)的類(lèi)。 #include class Animal public: Animal() void eat() couteatn ; ;36class Giraffe:private Animal public: Giraffe() void StrechNeck(double) coutstrechn;class Cat:public Animal public: Cat() void Meaw(

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論