当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++基础入门教程

C++对象布局及多态探索之菱形结构虚继承

    这次我们看看菱形结构的虚继承。虚继承的引入本就是为了解决复杂结构的继承体系问题。上一篇我们在讨论虚继承时用的是一个简单的继承结构,只是为了打个铺垫。

  我们先看看这几个类,这是一个典型的菱形继承结构。c100和c101通过虚继承共享同一个父类c041。c110则从c100和c101多重继承而来。

 struct c041
{
 c041() : c_(0x01) {}
 virtual void foo() { c_ = 0x02; }
 char c_;
};
struct c100 : public virtual c041
{
 c100() : c_(0x02) {}
 char c_;
};
struct c101 : public virtual c041
{
 c101() : c_(0x03) {}
 char c_;
};
struct c110 : public c100, public c101
{
 c110() : c_(0x04) {}
 char c_;
};


    运行如下代码:

    print_size_detail(c110)

  结果为:

    the size of c110 is 16

    the detail of c110 is 28 c3 45 00 02 1c c3 45 00 03 04 18 c3 45 00 01

  我们可以象上一篇一样,画出对象的内存布局。

    |c100,5 |c101,5 |c110,1 |c041,5 |

    |ospt,4,11 |m,1 |ospt,4,6 |m,1 |m,1 |vtpt,4 |m1 |

  (注:为了不折行,我用了缩写。ospt代表偏移值指针、m代表成员变量、vtpt代表虚表指针。第一个数字是该区域的大小,即字节数。只有偏移值指针有第二个数字,第二个数字就是偏移值指针指向的偏移值的大小。)

  可以看到对象的内存布局中只有一个c041,即祖父类的部分只有一份,且放在最后面。这就是菱形继承。对比前面几篇的讨论,我们可以知道,如果没有用虚继承机制,那么在c041对象的内存布局中会出现两份c041部分,这也就是所谓的v型继承。相应的对象布局为:c041+c100+c041+c101 +c110。在v型继承中是不能直接从c110,即孙子类,直接转型到c041,即祖父类的。因为在对象的布局中有两份祖父类的实体,一份从c100而来,一份从c101而来。编译器在决议时会存在二义性,它不知道转型后到底用哪一份实体。虽然可以通过先转型到某一父类,然后再转型到祖父类来解决。但使用这种方法时,如果改写了祖父类的成员变量的内容,runtime是不会同步两个祖父类实体的状态,因此可能会有语义错误。

  我们再分析一下上面的内存布局。普通继承的布局,顶层类在前面。多重继承时则按从左到右的顺序排。从c100和c101到c110的继承是普通继承,所以遵循这个原则,先是左父类再右父类,接下去是子类。而虚继承则要求将共享的父类放到整个对象布局的最后(即使虚父类没有被真正的共享也是如此,前在一篇的c020类就是这样。不知道打开优化开关后会不会有变化。)所以在上例中的祖父类也是被置于最后的。

  我们再看看对成员的访问情况。运行以下代码并查看相应的汇编代码。

    c110 c110;

    c110.c_ = 0x51;

    c110.c100::c_ = 0x52;

    c110.c101::c_ = 0x52;

    c110.c041::c_ = 0x53;

    c110.foo();

  对应的汇编代码为:

    01 00423993 push 1

    02 00423995 lea ecx,[ebp+fffff7f0h]

    03 0042399b call 0041de60

    04 004239a0 mov byte ptr [ebp+fffff7fah],51h

    05 004239a7 mov byte ptr [ebp+fffff7f4h],52h

    06 004239ae mov byte ptr [ebp+fffff7f9h],52h

    07 004239b5 mov eax,dword ptr [ebp+fffff7f0h]

    08 004239bb mov ecx,dword ptr [eax+4]

    09 004239be mov byte ptr [ebp+ecx+fffff7f4h],53h

    10 004239c6 mov eax,dword ptr [ebp+fffff7f0h]

    11 004239cc mov ecx,dword ptr [eax+4]

    12 004239cf lea ecx,[ebp+ecx+fffff7f0h]

    13 004239d6 call 0041df32

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接