虚继承派生类对象内存结构

在这里谈一下虚继承。前面写过派生类对象的内存结构,都是基于VS2010编译器的,不同的编译器对于继承的处理不同,但本质都是一样的。

虚继承是解决共享基类问题的。例如在菱形继承中

要想在派生类中共享基类。

先看下面一个例子:<"http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PHByZSBjbGFzcz0="brush:java;">#include using namespace std; class A{ public: A():a(10){}; int a; }; class B: public virtual A{ public: B():b(20){}; int b; }; class C:public virtual A{ public: C():c(30){}; int c; }; class D:public B, public C{ public: D():d(40){}; int d; }; int main() { cout<<"A size is "<VS2010运行结果如下:

A size is 4
B size is 12
C size is 12
D size is 24

之前在网上看过一些文章,解决虚继承共享对象的一个方案就是在虚函数表中添加共享对象的相对偏移。我们把D类对象各个部分打印出来看一下:


D d;
    int**p=(int**)&d;
    cout<<" 以4字节为单位,分成5部分:"<<endl;for(int=""i="0;"i<6;=""i++)=""cout<& lt;"第"<<i<<"个部分的值"<<p[i]<<endl;<=""pre=""& gt;<br>
以4字节为单位,分成5部分:<br>
第0个部分的值013078B0<br>
第1个部分的值00000014<br>
第2个部分的值013078A4<br>
第3个部分的值0000001E<br>
第4个部分的值00000028<br>
第5个部分的值0000000A<br>
<p></p>
<p> 可以看出第0部分和第2部分不是成员变量,其实是虚函数表指针,在虚函数表中记录着第5部分(就是虚基类A对象)相对其他对象的偏移。第0部分记录着相对 对象B和相对对象D的偏移(可以看出偏移20个字节),第2部分记录着相对C对象的偏移(偏移12个字节),可以查看一下:</p>
<p></p><preclass="brush:java;">cout<<p[0][1]<<endl; cout<<p[2][1]<<endl;<=""pre="">输出的结果就是20和12。<p>& lt;/p>
<p>至于为什么在虚函数表的第一个位置,我还没搞懂,不过我想应该是不同的编译器有不同的安排,但是它们的目的都是共享虚基类A对象。</p>
<p>在D中查找虚基类,首先找到虚函数表,然后找到偏移的大小,之后才能找到虚基类对象,可见虚基类降低了效率。<br>
<br>
</p>                        </p[0][1]<<endl;></pre></endl;>

以上就是对虚继承的一些简单介绍,如果想了解更多编程语言教程知识请登录e良师益友网。

posted @ 2014-09-13 17:18  语过添情want  阅读(111)  评论(0编辑  收藏  举报