【问题标题】:How a single vtable is tracking new virtual functions?单个 vtable 如何跟踪新的虚拟功能?
【发布时间】:2015-01-29 15:55:35
【问题描述】:

我正在使用 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字节,表示只存在一个指针。

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

根据this应该有两个vptr。

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

干杯。

【问题讨论】:

  • @Deduplicator ... 假设您确切了解调用了哪些覆盖程序,但并非所有人都这样做。
  • 很简单,whos ctor / dtor 类型中的一种就是执行。 (但请注意那里的 ctor-init-list。)
  • @madu 可能是调试器在欺骗你,只显示 vtable 的“基础”部分。整个 vtable 肯定也有一个新函数的条目,附加到它上面。
  • @Griwes:有虚拟调度,假装不这样是一个潜在的致命错误。类层次结构仅在目标派生最多的类型之下。
  • @madu is 只有一个“vptr”,但您的调试器只显示基类表中的两个条目。从您链接的问题的顶部答案:“实际上编译器将不同的 vtable 合并到一个 vtable 中”。

标签: c++ visual-studio virtual-functions vtable vptr


【解决方案1】:

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

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

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

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

【讨论】:

  • 1.甚至 vtable(如果有)的 存在 也是实现细节。 2. 看看std::iostream。据我统计,它有 3 个 vtable,因为每个实例都有 3 个 vtable 指针。 (在一些常见的实现上。) 3. 基本类型和既没有虚基也没有成员的类都没有 vtable 和 vtable-pointer。
  • @Serge 谢谢。我确实查看了内存内容,似乎没有第三个条目。我已经用内存截图更新了原始问题。
  • @Serge 你是对的。有一个条目。我在代码中犯了一个错误。这次真是万分感谢。奇怪的是为什么它不会出现。
猜你喜欢
  • 1970-01-01
  • 2019-04-17
  • 2022-07-01
  • 2016-09-24
  • 2013-01-14
  • 1970-01-01
  • 1970-01-01
  • 2011-08-15
  • 2013-01-09
相关资源
最近更新 更多