關(guān)于C++中菱形繼承和虛繼承的問題總結(jié)
前言
菱形繼承是多重繼承中跑不掉的,Java拿掉了多重繼承,輔之以接口。C++中雖然沒有明確說明接口這種東西,但是只有純虛函數(shù)的類可以看作Java中的接口。在多重繼承中建議使用“接口”,來避免多重繼承中可能出現(xiàn)的各種問題。本文將給大家詳細(xì)介紹關(guān)于C++菱形繼承和虛繼承的相關(guān)內(nèi)容,分享出來供大家參考學(xué)習(xí),話不多說了,來一起看看詳細(xì)的介紹吧。
繼承:
1. 單繼承–一個子類只有一個直接父類時稱這個繼承關(guān)系為單繼承
2. 多繼承–一個子類有兩個或以上直接父類時稱這個繼承關(guān)系為多繼承
例如下面這兩個例子:
例一(單繼承):
class A { public: int _a; }; class B : public A // B是 子類/派生類, 公有 繼承父類/基類 A { public: int _b; }; class C : public B //C是 子類/派生類, 公有繼承 父類/基類 B { public: int _c; };
例二(多繼承):
class A { public: int _a; }; class B { public: int _b; }; class C : public A , public B // 子類C同時公有繼承父類A和父類B { public: int _c; };
用圖很形象的表示一下:
但是在使用過程中,很容易出現(xiàn)一種繼承關(guān)系叫菱形繼承。就好比下面這種繼承方式。
class A { public: int _a; }; class B : public A { public: int _b; }; class C : public A { public: int _c; }; class D : public B, public C { public: int _d; };
繼承的方式簡單畫出來就是下面這樣:
我們在使用過程中會發(fā)現(xiàn)以下缺點:
1、 當(dāng)我們用D類創(chuàng)建出對象d時,可以訪問到_a,但是一旦編譯就會出現(xiàn)錯誤。錯誤說明為: C2385: 對“_a”的訪問不明確。從圖中也可以看出,如果用d訪問_a時,可能在B類里,也同時可能存在于c類中。這就是所謂的“二義性”;
2、雖然B類和C類都公有繼承A,但是在D類公有繼承B,C時,存放了兩份A類,造成了數(shù)據(jù)的冗余。
C++針對這種缺陷提出了另外一種繼承方式叫做虛繼承。
虛繼承
C++使用虛擬繼承(Virtual Inheritance),解決從不同途徑繼承來的同名的數(shù)據(jù)成員在內(nèi)存中有不同的拷貝造成數(shù)據(jù)不一致問題,將共同基類設(shè)置為虛基類。這時從不同的路徑繼承過來的同名數(shù)據(jù)成員在內(nèi)存中就只有一個拷貝,同一個函數(shù)名也只有一個映射。
◇語法:
class 派生類: virtual 基類1,virtual 基類2,…,virtual 基類n { …//派生類成員聲明 };
在有了虛繼承的概念后,我們就可以規(guī)避上面的缺點了。
class A { public: int _a; }; class B : virtual public A { public: int _b; }; class C : virtual public A { public: int _c; }; class D : public B, public C { public: int _d; };
當(dāng)我們使用了虛繼承時,繼承模型就改變?yōu)橄旅孢@樣:
由于我所使用的是vs2015,在此編譯器下對應(yīng)的處理方式就是這樣。將class B 和 class C設(shè)置為虛繼承后,編譯器將class A存放在了最下端,并在B和C類的前四個字節(jié)中存放了一個地址,當(dāng)我們訪問過去向下再多看四個字節(jié)時就會發(fā)現(xiàn)這其中存放了一個數(shù)字。而這個數(shù)字就類似于“偏移量”,記錄了該類的首地址距父類首地址之間的字節(jié)差距。比如class B中,我們找到對應(yīng)數(shù)字為14,但是這個數(shù)字是16進(jìn)制,轉(zhuǎn)為10進(jìn)制為20,在class B的首地址加上20個字節(jié)就恰好是class A的首地址,同理class C。
因此在class D訪問_a時,就不會產(chǎn)生二義性,_a數(shù)據(jù)也只存放了一份,解決了之前菱形繼承所帶來的問題。
但是還存在一個問題:當(dāng)我們求沒有使用虛繼承之前的class D的大小,結(jié)果是20,但是在使用了虛繼承后大小變?yōu)?4。所以雖然使用虛繼承解決數(shù)據(jù)冗余問題也帶來了性能上的損耗。(關(guān)于如何計算內(nèi)存大小,可以參考此鏈接。)
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對我們的支持。
欄 目:C語言
下一篇:利用C++如何覆蓋或刪除指定位置的文件內(nèi)容
本文標(biāo)題:關(guān)于C++中菱形繼承和虛繼承的問題總結(jié)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/1286.html
您可能感興趣的文章
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對數(shù)怎么表達(dá)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實現(xiàn)全排列算法的方法詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解
- 01-10APUE筆記之:進(jìn)程環(huán)境詳解
- 01-10c++中inline的用法分析
- 01-10如何尋找數(shù)組中的第二大數(shù)


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 04-02jquery與jsp,用jquery
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10C#中split用法實例總結(jié)
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語言求解撲克牌的順子及n個骰子