菱形继承

来源:互联网 发布:java 适配器模式 编辑:程序博客网 时间:2024/04/29 04:53

在探索菱形继承遇到的问题及其总结
先说什么是菱形继承如图(这只是一种)
这里写图片描述

#include<iostream>using namespace std;class A{public:    int _a;};class B: public A{public:    int _b;};class C: public A{public:    int _c;};class D:public C,public B{public:    int _d;};int main(){    D d;    d._a=1;    d._b=2;    d._c=3;    d._d=4;    return 0;}

以以上代码为例进行探索
在vs2008中,在运行中出现了
这里写图片描述
如图的错误。这是因为菱形继承具有二义性和冗杂性(如下图片可形象的进行了模拟)
这里写图片描述
D对象中有两个A成员。
如何解觉这个问题呢?
虚继承–解决菱形继承的二义性和数据冗余的问题
1. 虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。
2. 虚继承体系看起来好复杂,在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体
系结构,因为使用虚继承解决数据冗余问题也带来了性能上的损耗。
我们可以对上面的代码进行如下变化

“`

include

using namespace std;
class A
{

public:
int _a;
};
class B: virtual public A
{

public:
int _b;
};
class C: virtual public A
{
public:
int _c;
};
class D:public C,public B
{
public:
int _d;
};

int main()
{
D d;
d._a=1;
d._b=2;
d._c=3;
d._d=4;
return 0;
}
加virtual 以前的d的大小 20
这里写图片描述
加virtual 以后的大小24
这里写图片描述
打开监视窗口可看到如下
这里写图片描述
而解决这些问题在VS下使用的是偏移量,我们调用内存窗口可发现
这里写图片描述
class C的地址加20就是class A的地址,同理class B的地址加12就是class B的地址。sizeof(d)=24,所以在一定程度上会有性能损耗。

原创粉丝点击