本文编号:240327
今天我来给大家详细讲解一下关于C++之父本贾尼先生,挖下的小坑。关于继承中菱形继承的讲解。
在讲解菱形继承之前我先来给大家讲解一下,继承种类。其实分为以下两种。
第一:单继承
顾名思义:单继承指的是一个子类只有一个直接父类。
第二:多继承
顾名思义:多继承是指一个子类有多个父类
其中菱形继承是多继承的一种特殊情况
为什么说菱形继承是祖师爷挖下的坑呢?
其中包含两个方面的问题 第一点就是代码冗余 第二点就是会产生二义性
class Person
{
public:
string _name; // 姓名
};
class Student : public Person
{
protected:
int _num; //学号
};
class Teacher : public Person
{
protected:
int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:
string _majorCourse; // 主修课程
};
void Test()
{
// 这样会有二义性无法明确知道访问的是哪一个
Assistant a;
a._name = "peter";
}
这段代码清晰的展示了,为什么会存在二义性,Assistant不知到去调用哪个_name 成员
并且以上调试结果展示了代码冗余的问题,会创建两个变量占用空间,而且没达到我们想要的效果。
以上是出现的问题,那么我们该如何解决大佬给我们留下来的坑呢?
其实运用的就是关键字virtual 来虚继承。下面我们换一个场景来具体解释。
class A
{
public:
int _a;
};
// class B : public A
class B : virtual public A
{
public:
int _b;
};
// class C : public A
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;
}
以上代码为我们本次测试代码。这段代码在监视窗口其实看不出什么特殊效果,但是当我们打开内存窗口便会看到新天地。
在这里我们观察到了,A被放到了最下面,B对应的_b是3 C对应的_c是4,那么B、C中的另一个数字代表什么呢?
在看了B中第一个位置的地址后,神奇的发现了他是一个指针,指向的空间的下一个地址是一个偏移量,这个偏移量是B的起始地址相对于A的地址的偏移量。
这个是C中第一个位置的数字对应的地址,通过这个地址我们也找到了对用的偏移量,通过C的地址+偏移量我们可以明显的找到A。
以上是解决问题的方案,运用虚继承,形成一个虚基表。能找到对应地址,通过对应地址能找到偏移量从而找到了A的变量。
在解决了菱形继承后,让我们思考几个问题。
为什么虚继承能解决这个问题? 明显这样比原来的空间还大。
答:如果我们的A中含有多个成员变量,那么在虚继承中,存放一个指针的方式便成了节约空间成本的好方式了。
全文完。希望你们喜欢。