菱形继承与菱形虚拟继承
生活随笔
收集整理的這篇文章主要介紹了
菱形继承与菱形虚拟继承
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
菱形繼承
- 單繼承:一個子類只有一個直接父類時稱這個繼承關系為單繼承?
- 多繼承:一個子類有兩個或以上直接父類時稱這個繼承關系為多繼承
- 菱形繼承:菱形繼承是多繼承的一種特殊情況。?
?
來看看下面這段菱形繼承的代碼有什么問題呢?
#include <iostream>class A { public:int a; }; class A1 : public A { public:int a1; }; class A2 : public A { public:int a2; }; class B : public A1, public A2 { public:int b; };int main() {B b;return 0; }這樣看好像沒有什么問題,我們打開監視窗口發現:
發現b對象中含有兩份a,這是因為A1和A2分別繼承了A的成員,它們各自都有一份a,B繼承了A1A2,所以b對象中就有了兩份a,這就造成了數據的冗余性。
若要訪問成員a,要怎么訪問呢??看看下面的測試代碼:
int main() {B b;// 這樣無法明確知道訪問的是哪一個,出現了新的問題:二義性b.a = 1;// 顯示指定訪問哪個父類的成員解決了二義性的問題,但是數據冗余問題無法解決b.A1::a = 1;b.A2::a = 2;return 0; }總結:菱形繼承有數據冗余和二義性的問題!
?
虛擬繼承
虛擬繼承可以解決菱形繼承的二義性和數據冗余的問題。
上面的關系中,A1和A2繼承A時就可以使用虛擬繼承,就可以解決這些問題。
class A { public:int a; }; class A1 : virtual public A //虛擬繼承 { public:int a1; }; class A2 : virtual public A //虛擬繼承 { public:int a2; }; class B : public A1, public A2 { public:int b; };注意:虛擬繼承不要在其他地方去使用!
到底虛擬繼承解決數據冗余和二義性的原理是什么呢?
給出下面的測試代碼來看看:
B b; b.A1::a = 1; b.A2::a = 2; b.a1 = 3; b.a2 = 4; b.b = 5;- 來看看菱形繼承下的內存:?
這里可以看到數據冗余。
?
- 在看看菱形虛擬繼承下的內存:
從內存 1 中可以看到:b對象中 將A放到了最下面,A同時又屬于A1和A2,那A1和A2如何找到公共的A呢?
我們又看到內存1中A1和A2中有兩個地址(指針),打開內存2查看這個地址發現:它指向一張表,表中第二個元素剛好為A1到A的偏移量。
所以得出:通過了A1和A2的兩個指針,各自指向的一張表,這個表叫虛基表,這兩個指針叫虛基表指針。虛基表中存的偏移量。通過偏移量可以找到下面的A。
一張圖總結菱形虛擬繼承:
?
總結
以上是生活随笔為你收集整理的菱形继承与菱形虚拟继承的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 实现一个不能被继承的类
- 下一篇: Linux——进程信号(总结)