- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
对于此代码:
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/
我对 virtual inheritance 很感兴趣这件事给我带来了神秘感。让我们以 virtual inheritance 为例。 : struct Base { virtual void
虽然手头的问题已解决,但让我有点困惑的是什么数据用于构造类的虚表以及虚表的布局存储在哪里。如果有人可以提供澄清或指出一些可能满足我好奇心的信息,我将不胜感激。 背景 两个独立的 VC6.0 项目:一个
关于我的环境的信息 Mac OS 大苏尔:11.4 VS for Mac:8.10.6(内部版本 10) Xamarin.Android:11.3.0.4 SDK 工具版本:26.1.1 SDK平台工
根据我的理解,VTable 是调用最派生版本的函数所必需的。它将包含有关函数的最派生版本的条目......我的疑问是为什么我们需要为基类提供一个 VTable。因为使用基对象进行调用总是需要调用基类函
我读了这篇文章: https://shaharmike.com/cpp/vtable-part2/ 我不明白为什么在 vtable 中(在文章末尾)我们有这个指针: 0x400918 0x400820
#include #include using namespace std; class Foo { public: virtual void f1() { cou
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 关闭 9 年前。 这个问题似乎是题外话,因为它缺乏足够的信息来诊断问题。更详细地描述您的问题或inclu
class Base { public: virtual void function1() {}; virtual void function2() {}; }; class D1:
Variant-like 类型通常通过模拟 Vtables 来实现,参见示例 https://www.youtube.com/watch?v=uii2AfiMA0o 现在,作为替代方案,我们可以简单地
假设我有一个继承自 B 类和 C 类的 A 类(多重继承)。A 类有多少 vtable 成员?单继承是什么情况? 此外,假设: Class A : Public B {} 和: B* test = n
我知道这里有很多关于 vtables 的问题,但我还是有点困惑。 只有当我们有一个指向基类的指针来解析要调用派生类的哪个虚函数时,才使用 vtables 吗? 在我下面的示例中,在第一种情况下,是否在
我有一些关于虚拟析构函数和 vtable 的具体问题。 假设我有以下代码: class Base { public: virtual ~Base(); }; class Child : pub
这个问题在这里已经有了答案: What is a vtable in C++ [duplicate] (3 个答案) Why do we need a virtual table? (5 个答案)
如何在位置无关代码中实现虚函数? 我知道如果我的类有虚函数,编译器通常会为它生成一个 vtable,其中包含所有虚函数的地址,并在我的类的每个对象中存储一个指向 vtable 的指针。 现在,如果我的
网上有很多关于虚表的资源。他们通常对他们有相同的陈述: "只要类本身包含虚函数或重写父类的虚函数,编译器就会为该类构建一个 vtable。这意味着并非所有类都有编译器为它们创建的 vtable。 vt
我对 vtables 的理解是,如果我有一个带有虚函数 speak() 的类 Cat,它有子类 Lion 和 HouseCat,则有一个 vtable 将 speak() 映射到每个子类的正确实现。于
vtable 包含指向那个类的虚函数的指针。它是否也包含指向非虚函数的指针? 谢谢! 最佳答案 这是一个实现细节,但不是。如果一个实现将指向非虚函数的指针放入虚表中,它就不能使用这些指针进行函数调用,
我们有没有virtual table对于 abstract class ? 最佳答案 首先,vtables 的使用是实现定义的,而不是标准强制要求的。 对于使用 vtable 的实现,答案是:是的,通
你能解释一下编译器是否为一个有虚函数的类生成了 vtable 并且没有使用那个类(对象不是以任何形式创建的)。比如说, class A { public:
我对 C++ 和虚拟继承感到好奇 - 特别是解决 bass 类和子类之间的 vtable 冲突的方式。我不会假装理解它们如何工作的细节,但到目前为止我所看到的是它们是由于该分辨率而使用虚函数造成的一个
我是一名优秀的程序员,十分优秀!