c++ - g++ -fdump-class-hierarchy 的输出中的第一个 (int (*)(...))0 vtable 条目是什么?

标签 c++ gcc virtual-functions vtable

对于此代码:

class B1{
public:  
  virtual void f1() {}  
};

class D : public B1 {
public:
  void f1() {}
};

int main () {
    B1 *b1 = new B1();
    D  *d  = new D();

    return 0;
}

编译后,我用g++ -fdump-class-hierarchy得到的vtable是:

Vtable for B1
B1::_ZTV2B1: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI2B1)
16    B1::f1


Vtable for D
D::_ZTV1D: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI1D)
16    D::f1

我不明白像 (int ()(...))0* 这样的条目对应的是什么。当然,它的意思是,它是一个返回 int 并接受无限数量参数的函数,我对此一无所知。 这个函数指针对应于哪个函数?你怎么知道的?我的是64位机。

第二个函数指针在末尾有一个关联的地址??这对应于谁?

编辑

编译器,我用的是g++:

g++ -v
Using built-in specs.
Target: x86_64-suse-linux
Configured with: ../configure --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/usr/lib64 --libexecdir=/usr/lib64 --enable-languages=c,c++,objc,fortran,obj-c++,java,ada --enable-checking=release --with-gxx-include-dir=/usr/include/c++/4.4 --enable-ssp --disable-libssp --with-bugurl=http://bugs.opensuse.org/ --with-pkgversion='SUSE Linux' --disable-libgcj --disable-libmudflap --with-slibdir=/lib64 --with-system-zlib --enable-__cxa_atexit --enable-libstdcxx-allocator=new --disable-libstdcxx-pch --enable-version-specific-runtime-libs --program-suffix=-4.4 --enable-linux-futex --without-system-libunwind --with-arch-32=i586 --with-tune=generic --build=x86_64-suse-linux
Thread model: posix
*gcc version 4.4.1 [gcc-4_4-branch revision 150839] (SUSE Linux)*

最佳答案

这些是到顶部的偏移量(需要多重继承)和 typeinfo (RTTI) 指针。

来自 Itanium ABI (你没有使用安腾编译器,但他们对此的描述非常好):

The offset to top holds the displacement to the top of the object from the location within the object of the virtual table pointer that addresses this virtual table, as a ptrdiff_t. It is always present. The offset provides a way to find the top of the object from any base subobject with a virtual table pointer. This is necessary for dynamic_cast in particular.
(In a complete object virtual table, and therefore in all of its primary base virtual tables, the value of this offset will be zero. [...])

The typeinfo pointer points to the typeinfo object used for RTTI. It is always present. All entries in each of the virtual tables for a given class must point to the same typeinfo object. A correct implementation of typeinfo equality is to check pointer equality, except for pointers (directly or indirectly) to incomplete types. The typeinfo pointer is a valid pointer for polymorphic classes, i.e. those with virtual functions, and is zero for non-polymorphic classes.


更详细的顶部偏移 (根据要求)

假设您有一个派生类 D派生自基类 B1 .当您尝试转换 D 时会发生什么?要键入的实例 B1 ?由于函数采用 B1对象对 D 一无所知,D 的一部分vtable 也必须是有效的 B1虚表。这很容易 - 只需开始 D vtable 看起来像 B1 vtable,然后添加我们需要的任何其他条目。期望 B1 的函数会很高兴,因为他们不会使用 vtable 的任何部分超出他们对 B1 的期望。 .

但是,如果 D现在源自B2 ?指向 D 的指针vtable 不能是两者有效的 B1 vtable 有效B2虚表!编译器通过附加一个单独的 B2 来解决这个问题。 vtable 到我们合并后的 D/B1 vtable,并在我们尝试从 D 转换时手动调整 vtable-pointer到 B2 .

然而,这导致了一个新问题——当我们尝试从 B2 中强制转换 back 时会发生什么?到 D ?编译器不能仅仅将 vtable-pointer 向后调整与之前调整指针的量相同,因为它实际上并不知道确定 B2我们给它的对象是 D !特别是, dynamic_cast<D>() 必须能够判断我们的对象是否属于 D 类型.为此,它需要访问对象的 RTTI,而对于 that,它需要知道原始对象的 vtable 的起点在哪里。这就是 offset-to-top 值的目的——它为我们提供了到原始对象 vtable 开头的偏移量,我们得到了对象的 RTTI,C++ 的复仇之神允许我们的裁剪再生长一个季节。

This page有一些很好的 vtable 布局示例(在 Table 1c 下)。请注意,由于使用了virtual inheritance,它们稍微复杂一些。 ,这会为每个子类的 vtable 添加一个额外的偏移量。

关于c++ - g++ -fdump-class-hierarchy 的输出中的第一个 (int (*)(...))0 vtable 条目是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5712808/

相关文章:

c++ - 这个签名中的第二个参数是什么意思?

c++ - 从映射中删除动态分配的内存

c++ - 使用 MinGW GCC 4.5.0 配置 NetBeans 6.9 时遇到问题

c++ - 以自身为参数的抽象基类虚纯方法

c++ - 虚函数实现和多重继承

c++ - 显示对象中的字符数组

c++ - 我应该使用 volatile c++ 吗?

c - 如何防止 strcpy() 被优化

c - 如何移动寄存器中标签的地址

C++多菱形继承和纯虚函数