C++菱形繼承問題

1. 什麼是菱形繼承

基類A,B繼承A,C繼承A,D繼承BC。D中的B對象有A,D中的C對象還有A,重複了,如果調用函數,則不知道是B中的函數還是C中的函數。
在這裏插入圖片描述

#include <iostream>
using namespace std;

class A {
public:
	A() { a = 1; }
	~A() {}
	void fun() { cout << "in class A" << endl; }
	int a;
};

class B : public A {
public:
	B() { b = 2; }
	~B() {}
	void fun() { cout << "in class B" << endl; }
	int b;
};

class C : public A {
public:
	C() { c = 3; }
	~C() {}
	void fun() { cout << "in class C" << endl; }
	int c;
};

class D : public B, public C {
public:
	D() { d = 4; }
	~D() {}
	int d;
};

int main() {
	D od;
	//od.fun();//會報錯,fun不明確,不知道是誰的fun
	auto add_ba = &od.B::A::a;
	auto add_ca = &od.C::A::a;
	cout << "addr of a in B = " << add_ba << endl;
	cout << "addr of a in C = " << add_ca << endl;
	return 0;
}

輸出:
在這裏插入圖片描述
B中有個A對象,C中有個A對象,兩個A對象不一樣,D中就有兩個A對象。
菱形繼承存在二義性與數據冗餘問題。
使用虛繼承解決,虛繼承的做法如下。

2. 虛繼承

虛繼承的具體操作方式如下:

#include <iostream>
using namespace std;

class A {
public:
	A() { a = 1; }
	~A() {}
	void fun() { cout << "in class A" << endl; }
	int a;
};

class B : virtual public A {
public:
	B() { b = 2; }
	~B() {}
	void fun() { cout << "in class B" << endl; }
	int b;
};

class C : virtual public A {
public:
	C() { c = 3; }
	~C() {}
	void fun() { cout << "in class C" << endl; }
	int c;
};

class D : public B, public C {
public:
	D() { d = 4; }
	~D() {}
	int d;
};

int main() {
	D od;
	//od.fun();
	auto add_ba = &od.B::A::a;
	auto add_ca = &od.C::A::a;
	cout << "addr of a in B = " << add_ba << endl;
	cout << "addr of a in C = " << add_ca << endl;
	return 0;
}

實際中的內存關係如下:
在這裏插入圖片描述
此時D類對象od的佈局如左側所示,先是B類對象(B類對象此時只包含一個指針和b),然後是C類對象(C類對象此時只包含一個指針和c),然後是D類獨有的d,最後是A類對象中的a。

此時的結構有些奇怪:
在這裏插入圖片描述
B中的a與C中的a地址相同:
在這裏插入圖片描述
沒有了冗餘現象,具體來說是通過B類對象和C類對象的指針實現的,指針指向的區域存儲的是該類對象到基類對象的一個偏移量,如B中的指針就是存儲的B類對象到A類對象的偏移量,一個指針4個字節,偏移量爲20說明相差5個指針的距離

sizeod(od)=24,abcd佔16個字節,B中的指針和C中的指針一共8字節,加起來爲24.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章