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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值