2014-12-01 79 views
-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; 
} 

这是我所看到的在调试时: enter image description here

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

但是,正如你所见,只有一个vptr/vftable。但机制工作正常。

我以为有第二个vptr,我不能在观察窗口看到,所以我打印出对象的大小。它是4个字节,表示只有一个指针存在。

那么这是如何与新增虚拟功能?根据this应该有两个vptrs。

编辑:我检查了vftable的内存内容,因为Serge建议并且确实有三个条目。 enter image description here 由于某种原因,它没有显示在调试器中。

干杯。

+0

不,因为当您创建派生对象时,vtable中的条目将被派生的虚拟函数的地址替换(如果派生的虚函数派生出来的话)。这是在构造对象时完成的,它解释了为什么你不应该在构造函数/析构函数中调用虚函数。 – Borgleader 2014-12-01 15:42:48

+0

为什么要在对象中有两个?一个就足够了,派生类vtable基于基类,为更多虚拟添加额外条目并替换其他条目以指向新实现。 – Deduplicator 2014-12-01 15:44:05

+0

@Borgleader:在ctors和dtors中调用虚函数很好。 – Deduplicator 2014-12-01 15:44:41

回答

1

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

  • 有一个且只有一个虚表(*)每类(而不是每个对象)
  • 每个对象都有一个指向它的虚函数表(它的实际类的一个)
  • _vfptr是祖先类的属性,调试器显示它的祖先类下,因此只显示该类

但可以肯定的真正_vtable包含了其他虚拟方法条目定义的方法...尾部呃调试器显示的条目!

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

+0

1.即使vtable的* existance *(如果有)也是一个实现细节。 2.看看'std :: iostream'。根据我的计数,它有3个vtable,因为每个实例都有3个vtable指针。 (在一些常见的实现上)。3.既不是基本类型,也不是既没有虚拟基础也没有成员的类具有虚表和虚表指针。 – Deduplicator 2014-12-01 20:10:27

+0

@Serge谢谢。我确实看过记忆内容,似乎没有第三项。我用内存截图更新了原始问题。 – madu 2014-12-02 00:07:51

+0

@Serge你是对的。有一个条目。我在代码中犯了一个错误。这次真是万分感谢。奇怪为什么它不显示。 – madu 2014-12-02 02:49:51