施工方案下载免费网站,wordpress 文章发布失败,丽江网站开发找千素网,网站制作专业的公司叫什么1.菱形继承#xff08;钻石继承#xff09;#xff1a;两个子类继承同一父类#xff0c;而又有子类同时继承这两个子类。例如B,C两个类同时继承A#xff0c;但是又有一个D类同时继承B,C类。
2.菱形继承的对象模型
class A
{
public:int _a;
};class B :public A
{
p…1.菱形继承钻石继承两个子类继承同一父类而又有子类同时继承这两个子类。例如B,C两个类同时继承A但是又有一个D类同时继承B,C类。
2.菱形继承的对象模型
class A
{
public:int _a;
};class B :public A
{
public:int _b;
};
class C :public A
{
public:int _c;
};
class D :public B,public C
{
public:int _d;
};上述的代码对应的菱形继承的对象模型如下图所示 3.菱形继承所带来的问题 1由上图的对象模型可以看出D的对象中有两份A成员造成了数据的冗余。使用sizeof去验证可以发现d的大小为20个字节。
2会造成基类子对象重复即二义性。造成访问基类的成员不明确。 4.解决菱形继承所带来的问题 1要解决二义性很简单可以显示的指定访问哪个父类的成员但是这个还是不能从根本上解决这个问题。如
D d;
d.B::_a;
//d.C::_a;
//上述两种方法取其一就可以规避这个问题2要从本质上解决上述问题需要采用虚继承虚继承是一种机制类通过虚继承指出它希望共享虚基类的状态。对给定的虚基类无论该类在派生层次中作为虚基类出现多少次只继承一个共享的基类子对象共享基类子对象称为虚基类。虚基类用virtual声明继承关系就行了。这样一来D就只有A的一份拷贝。 如
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;
};采用虚继承和显示指定访问父类成员对对象所产生的的影响有什么不同呢显示指定访问并不能起到一改全改的作用那么就会造成一个对象d有两个不相同的成员_a,明显是不符合常规的。 1. 显然我们不用显示的指定访问哪个父类的成员但是可以清晰看到d的大小并不是期望中的16而是24个字节这是为什么呢5.深入理解虚继承 现在来了解多出来的四个字节究竟是什么首先我们通过调试——内存查看对象d的地址的数据可以看到如下现象 12中存放的数据究竟是用来表示什么的呢再将d._a分别赋值成为0和4通过内存窗口观察d的地址的数据 由图可以看到末排的地址存放的数据刚好是d._a的值的大小那么多出来的第一排和第三排的数据看起来似乎是两个地址输入地址查看一下数据
明显可以看到两个地址存放的数据是每个对象相对于基类的成员的偏移量对应的每个地址所代表的意义如下
这样也就可以解释为什么d的大小为24个字节因为虚继承引入了间接性指针 6.在虚继承的前提下重新建立对象模型
7.在菱形继承且为虚继承的前提下讨论虚基表为什么首先不存偏移量而是在存偏移量之前预留了一个0x0000 0000的位置呢 1首先设置一个菱形继承且为虚继承每个子类既重写了父类的虚函数还拥有自己的虚函数
class A
{
public:virtual void f1(){cout A::f1() endl;cout endl;}virtual void f2(){cout A::f2() endl;cout endl;}int _a;
};class B :virtual public A
{
public:virtual void f1(){cout B::f1() endl;cout endl;}virtual void f3(){cout B::f3() endl;cout endl;}int _b;
};
class C :virtual public A
{
public:virtual void f1(){cout C::f1() endl;cout endl;}virtual void f4(){cout C::f4() endl;cout endl;}int _c;
};class D :public B,public C
{
public:virtual void f1(){cout D::f1() endl;cout endl;}virtual void f5(){cout D::f5() endl;cout endl;}int _d;
};用菱形继承的模型图来表示关系就是 通过实例化出对象d并查看内存可以看到对象布局可以看到有五个类似地址的部分一一通过内存窗口查看内容发现三张为虚表存放虚函数两张为虚基表存放偏移量的在下图中用不同的颜色标注出来了 通过内存窗口查看各个虚基表的地址 可以看到虚基表的开始预留一个位置是用来存放虚基表和虚表的地址之差的。 内存分布模型
那么可以看到实例化出来的对象d的对象模型为
至于虚表存放的虚函数顺序是怎么存放的 http://blog.csdn.net/skyroben/article/details/68192874