菱形继承和虚拟继承

菱形继承导致数据冗余和二义性,而虚拟继承通过虚基表解决了这些问题。虚拟继承使得多继承的子类只保留一份基类实例,从而避免数据冗余。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

菱形继承

      当我们对继承有了一定了解就可以探究更复杂的继承关系,菱形继承就是一种复杂的继承。

首先先了解几个概念

单继承:一个子类只继承了一个父类。

多继承:一个子类继承了多个父类

菱形继承就是他们的继承关系形成了一个菱形,如图。

我们再通过代码才说明一个问题。

class Person
{
public:
	string _name = "djh";
};

class Student : public Person
{
public:
	int _number = 99;// 学号
};
class Teacher : public Person
{
public:
	int _job = 101;//工号
};

class Assistant : public Student, public Teacher
{
public:
	int _age = 18;//年龄
};
int main()
{
	Assistant a;
	a._name = "DJH"
}

Student和Teacher这两个类都继承了Person这个基类,然后Assistant又继承了Student和Teacher。他们都继承了_name这个成员,然后再被Assistant继承,那么这个_name是哪个_name呢?根本说不清。

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份

我们可以通过显示访问的方法解决数据二义性的问题,但是数据冗余的问题却无法得到根本的解决。

int main()
{
	Assistant a;
	a.Student::_name = "DJH";
	a.Teacher::_name = "djh";
	return 0;
}

这时候就出现了虚拟继承。

 

虚拟继承

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用。

class Person
{
public:
	string _name = "djh";
};

class Student : virtual public Person
{
public:
	int _number = 99;// 学号
};
class Teacher : virtual public Person
{
public:
	int _job = 101;//工号
};

class Assistant : public Student, public Teacher
{
public:
	int _age = 18;//年龄
};

继承的时候加上关键字代表虚拟继承就可以了,那么他是如何解决数据冗余和二义性的问题的呢?

 

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;
};
int main()
{
	D d;
	d.B::a = 1;
	d.C::a = 2;
	d.b = 3;
	d.c = 4;
	d._d = 5;
	return 0;
}

从图中我们可以看出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。

如下图

以上就是继承中比较复杂的菱形继承和虚拟继承。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值