菱形继承
一:分析菱形继承的问题
FIRST:
单继承:一个子类只有一个直接父类。
#include <iostream>
#include <string>
using namespace std;
class people
{
string _name;
};
class student : public people
{
int _id;
};
int main()
{
student s;
return 0;
}
多继承:
菱形继承
:顾名思义class a被 class b, class c继承。然后class d 又同时继承class b和class c。这种继承关系犹如一个菱形:
二:剖析虚继承是怎么解决二义性和数据冗余的
菱形继承一方面让代码的编写和逻辑思想更贴切于生活,同时(every sword has two blades ) :任何事情都有两面性:
一:菱形继承 中派生类对象包含多个基类对象的数据,譬如上图 teaching secretary类 同时继承了 student 类中的 _name和 people类中的 _name两份_name造成数据冗余。
二:同时继承_name时,当我们执行如下代码:teaching secretary t;
t._name = "张三"; 时,就不清楚是给继承student类中的_name复制,还是 给teacher中的_name赋值。此时产生二义性。
那么 编译器 是如何解决这种问题的: 它构造出这样一种模型:虚继承。(VIRTURE)
· #include <iostream>
using namespace std;
class people
{
public:
int _a;
};
class student:virtual public people
{
public:
int _b;
};
class teacher:virtual public people
{
public:
int _c;
};
class TeachingSecretary : public student, public teacher
{
public:
int _d;
};
int main()
{
TeachingSecretary T;
T.student::_a = 10;
T.teacher::_a = 20;
return 0;
}
首先使用虚继承,首先编译肯定通过了,其次当你 不指定类作用域为_a 复制时不会再出现二义性的问题。代码会正 常运行。
那么到底为何编译器是怎样做的: 就要通过内存窗口一探究竟(监视窗口编译器为了让人看得更舒服,有的就优化了显示):
同一段代码: 此时输出结果:
此时为何 是24类嘞~编译器是这样做的:
首先 在内存窗口中:可以看到 当用&T时:
第一行和第二行 会有默认的 数值:这个 数值 00 c0 58 0c 代表什么意思呢:再看
其实在内存中这些数据是这样存储的:
构造:菱形虚拟继承对象模型
(every coin has two sides)
虽然通过菱形虚拟继承对象模型有效的解决了菱形继承的数据冗余和二义性问题。但同时做生意一样,
当二义性的类属性成员只有像上一个例子一样,为了解决一个int (4字节的问题),开辟了存放两个虚地址表地址的空间(共计8字节)
就有点得不偿失了。但是当冗余的数据很大,占很大内存,那使用虚拟对象模型简直完美~
故:这种模型还是对我们很有帮助,可以真正解决问题哒~