设为首页 加入收藏

TOP

C对象布局及多态实现探索之虚继承
2014-11-23 22:16:23 】 浏览:204
Tags:对象 布局 实现 探索 继承

  下面我们来看虚继承。首先看看这C020类,它从C010虚继承:}


struct C010
{
 C010() : c_(0x01) {}
 void foo() { c_ = 0x02; }
 char c_;
};
struct C020 : public virtual C010
{
 C020() : c_(0x02) {}
 char c_;
};
  运行如下代码,查看对象的内存布局:


PRINT_SIZE_DETAIL(C020)
  结果为:


The size of C020 is 6
The detail of C020 is c0 c2 45 00 02 01
  很明显对象的起始处是一个指针,然后是子类的成员变量,接下来是父类的成员变量。和以前的讨论不同的是由于使用了虚继承,父类的成员变量被放到了最后面。


  运行如下的代码:


C020 c020;
c020.C010::c_ = 0x04;
  由于子类中的变量和父类中的变量重名,所以我们必须用这种方式来访问属于父类的成员变量,普通情况下不需要这种写法。我们看看后面这行代码对应的汇编代码:


0042387E mov eax,dword ptr [ebp FFFFF82Ch]
00423884 mov ecx,dword ptr [eax 4]
00423887 mov byte ptr [ebp ecx FFFFF82Ch],4
  前面说过对象的起始是一个指针,第1行指令取到这个指针的值,第2行把这个指针指向的地址后移4字节后的值(做为一个4字节的值)取出来。执行完这句我们看看ecx寄存器,可知取出来的值为5。最后一行是真正的赋值指令,它通过在对象的起始处(即[ebp FFFFF32Ch])加上ecx中的值做偏移值(即5)来得到赋值的目的地址。接合前面的对象布局输出,我们可以发现从对象起始地址开始加5字节的偏移值,刚好得到父类的成员变量的地址。这样我们可以大致分析出直接虚继承的子类的对象布局。


|子类5            |父类1    |
|偏移值指针4,5|子类成员变量1|父类成员变量1|


  (注:第一个数字为所在区域的长度(字节数),偏移值指针后的第二个数字为该指针指向的偏移值。后同。)


  通过查看内存可以发现偏移值指针指向的内存前4字节为0,我不知道它的具体的用途是什么。接下来的4字节是一个32位的整数,也就是真正的偏移值。即从子类的起始位置到被虚继承的父类的起始位置的偏移值,在我们前面的例子中这个值为5(一个指针加一个char成员变量)。


  通过这个分析我们可以看到在虚承继的情况下,通过子类的对象访问父类的普通成员变量的效率是相当低的。如果必须用到虚继承,也应该尽量不要在父类中放置普通成员变量(静态成员变量不受影响)。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇基于.NET的多线程编程入门 下一篇C对象布局及多态实现探索之虚函数..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目