-1

我正在使用 VS 2013 并试图查看 vptr 和 vftable 如何在对象级别工作。所以我有以下课程:

#include<iostream>
using namespace std;

class baseClass
{
public:
    void nonVirtualFunc() {}
    virtual void virtualNonOverriddenFunc() {}
    virtual void virtualOverriddenFunc() {}
};

class derivedClass : public baseClass
{
public:
    virtual void virtualOverriddenFunc() {}
    virtual void derivedClassOnlyVirtualFunc() { cout << "derivedClass" << endl; }
};


int main(int argc, char** argv) {

    derivedClass derivedClassObj2;
    cout << "Size of derivedClassObj: " << sizeof(derivedClassObj2) << endl;

    return 0;
}

这就是我在调试时看到的: 在此处输入图像描述

理论上应该有两个 vptr。一个用于baseClass 的vftable 和一个用于derivedClass 以跟踪新添加的derivedClassOnlyVirtualFunc()。

但正如你所见,只有一个 vptr/vftable。但该机制运作良好。

我以为在监视窗口中看不到第二个 vptr,所以我打印了对象的大小。它是 4 个字节,表示只存在一个指针。

那么这如何与新添加的虚函数一起工作呢?

根据这个应该有两个vptr。

编辑:我按照 Serge 的建议检查了 vftable 的内存内容,确实有三个条目。 在此处输入图像描述 由于某种原因,它没有出现在调试器中。

干杯。

4

1 回答 1

1

vtable 实现依赖于编译器。对象的大小(4 个字节)表明 vtable 没有在对象中复制,因为 4 个字节只是一个指针。我的理解是:

  • 每个类只有一个vtable (*)(不是每个对象)
  • 每个对象都有一个指向其 vtable 的指针(它的实际类之一)
  • 作为_vfptr祖先类的属性,调试器将其显示在祖先类下,因此仅显示该类中定义的方法

但可以肯定的是,真正的 _vtable 包含其他虚拟方法的条目......在调试器显示的条目之后!

(*) 当您考虑_vfptr阵列的内部组织时,事情变得更加困难。事实上,它可以看作包含所有祖先类的 vtable 的副本。这里, 的前 2 个条目derivedClass对应于 的 vtable baseClass。但是,如果您打开一个内存窗口,并检查 _vfptr 地址(0x00d9ba68在您的示例中)是什么,您应该会在一个空条目之前看到第三个条目(至少这是我的 MSVC Express 2008 显示的内容)。这第三个条目对应于函数derivedClassOnlyVirtualFunc,但正如我上面所说的那样,调试器没有显示出来。

于 2014-12-01T16:34:08.537 回答