您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關C++中菱形繼承和虛繼承的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
繼承:
1. 單繼承–一個子類只有一個直接父類時稱這個繼承關系為單繼承
2. 多繼承–一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承
例如下面這兩個例子:
例一(單繼承):
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; };
用圖很形象的表示一下:
但是在使用過程中,很容易出現一種繼承關系叫菱形繼承。就好比下面這種繼承方式。
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; };
繼承的方式簡單畫出來就是下面這樣:
我們在使用過程中會發現以下缺點:
1、 當我們用D類創建出對象d時,可以訪問到_a,但是一旦編譯就會出現錯誤。錯誤說明為: C2385: 對“_a”的訪問不明確。從圖中也可以看出,如果用d訪問_a時,可能在B類里,也同時可能存在于c類中。這就是所謂的“二義性”;
2、雖然B類和C類都公有繼承A,但是在D類公有繼承B,C時,存放了兩份A類,造成了數據的冗余。
C++針對這種缺陷提出了另外一種繼承方式叫做虛繼承。
虛繼承
C++使用虛擬繼承(Virtual Inheritance),解決從不同途徑繼承來的同名的數據成員在內存中有不同的拷貝造成數據不一致問題,將共同基類設置為虛基類。這時從不同的路徑繼承過來的同名數據成員在內存中就只有一個拷貝,同一個函數名也只有一個映射。
◇語法:
class 派生類: virtual 基類1,virtual 基類2,…,virtual 基類n { …//派生類成員聲明 };
在有了虛繼承的概念后,我們就可以規避上面的缺點了。
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; };
當我們使用了虛繼承時,繼承模型就改變為下面這樣:
由于我所使用的是vs2015,在此編譯器下對應的處理方式就是這樣。將class B 和 class C設置為虛繼承后,編譯器將class A存放在了最下端,并在B和C類的前四個字節中存放了一個地址,當我們訪問過去向下再多看四個字節時就會發現這其中存放了一個數字。而這個數字就類似于“偏移量”,記錄了該類的首地址距父類首地址之間的字節差距。比如class B中,我們找到對應數字為14,但是這個數字是16進制,轉為10進制為20,在class B的首地址加上20個字節就恰好是class A的首地址,同理class C。
因此在class D訪問_a時,就不會產生二義性,_a數據也只存放了一份,解決了之前菱形繼承所帶來的問題。
但是還存在一個問題:當我們求沒有使用虛繼承之前的class D的大小,結果是20,但是在使用了虛繼承后大小變為24。所以雖然使用虛繼承解決數據冗余問題也帶來了性能上的損耗。(關于如何計算內存大小,可以參考此鏈接。)
關于“C++中菱形繼承和虛繼承的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。