好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

vtordisp

vtordisp

关于 vtordisp 知多少?

 

我相信不少人看到这篇文章,多半是来自于对标题中“ vtordisp ”的好奇。其实这个关键词也是来源于我最近查看对象模型的时候偶然发现的。我是一个喜欢深究问题根源的人(有点牛角尖吧),所以当我第一次发现 vtordisp 的时候,我也是很自然的把它输进 google 查找相关资料,但是结果令我不太满意。不过,即使如此,我还是把与它相关的资料整理如下,并结合自己的理解和大家分享一下,希望能共同学习进步。

首先从产生“ vtordisp ”问题的那个例子开始。

 

class Base
{
public:
    int base;
    virtual void fun(){}
};
class Der:virtual public Base
{
    int der;
public:
    Der(){}
    virtual void fun(){}
};

 

Der对象模型如下:

 

 

我们发现对象的 8 字节偏移处,使用了 4 个字节存储了虚基类 Base 的 vtordisp 。在我的前一篇博客内,我们并未涉及这个内容。首先,我从查阅一下 vtordisp 的 MSDN 的解释 。 MSDN 给出的解释是: 虚继承中派生类重写了基类的虚函数,并且在构造函数或者析构函数中使用指向基类的指针调用了该函数,编译器会为虚基类添加 vtordisp 域 。

然而,经过 VS2010 的测试,我们发现上述示例代码便会产生 vtordisp 字段!条件是。

1.  派生类重写了虚基类的虚函数。

2.  派生类定义了构造函数或者析构函数。

这两个条件缺一不可,这个结论与 这里的描述 是一致的。

但是,到目前为止,我们只是确定了 vtordisp 的产生条件而已。它究竟为什么存在对象的模型中,对象如何使用它,我们仍一无所知!

按照前边的资料内容,这个字段和编译选项 /vd 相关。 /vd 被称为构造置换(具体什么意思,我也不太清楚,惭愧!),它所解决的问题是: 由于对类的虚拟基的置换与对其派生类的置换之间有差异,可能会向虚函数传递错误的  this  指针。   该解决方案向类的各个虚拟基提供称作  vtordisp  字段的单个构造置换调整 。但是如何构造产生错误 this 指针的测试用例,请恕作者才疏学浅不能给出,也希望看到此文的大牛们给出测试用例。

另外,编译器还提供了预编译命令关闭 vtordisp 字段的产生。

#pragma vtordisp({on|off})

在我们刚才代码的前段关闭该字段的产生,事实证明也不会产生预期的错误,这的确匪夷所思,园子内 另一篇博客下 的评论也表达了同样的意思。而且,更重要的是,这个预编译命令一直说会在未来的 VC 版本内取消,但是我在 VS2010 下还是看到了它的身影。最后,我在一篇 描述 C++ 代理的文章 中找到了另外一些线索。按照它的描述,这个字段一直存储为 0 。为了证明该猜测,我们用 Der 构造一个对象 der ,并查看该对象的内存内容。  

参考对象模型,该对象 vtordisp 的位置的确存储的是 0 。

曾经我遇到过一个虚拟继承的实例,在对象的初始化过程中会修改 vtordisp 字段,但是每次在初始化结束前都会把 vtordisp 减去一个常量使得它的最终结果为 0 。而且没有出现任何访问该字段的汇编指令!(既然不访问,为何浪费指令设置它的值呢?)因此,这也让我怀疑编译器设计 vtordisp 的合理性。

无论如何,我们发现对编译器产生的 vtordisp 字段了解的是太少了。单纯依靠代码动作猜测该字段存在的含义可行性十分有限,希望对此内容清楚的园友能给出合理的解释。

作者: Florian

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。[若本文对你有所帮助,还望多多推荐支持~!]

 

分类:  C++

标签:  vtordisp

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于vtordisp的详细内容...

  阅读:40次