所有类都有编译器为其创建的 Vtable 吗?
网上有很多关于 VTable 的资源。它们通常有相同的声明:
“每当类本身包含虚函数或覆盖父类中的虚函数时,编译器都会为该类构建 vtable。这意味着并非所有类都创建了 vtable vtable 包含指向该类中的虚函数的函数指针。每个类只能有一个 vtable,并且同一类的所有对象将共享同一个 vtable。”
那么为什么这意味着不所有类都有一个由编译器为其创建的 vtable 吗?是因为somc类没有虚函数吗?
There are many resources online about VTables. They commonly have the same statement regarding them:
"Whenever a class itself contains virtual functions or overrides virtual functions from a parent class the compiler builds a vtable for that class. This means that not all classes have a vtable created for them by the compiler. The vtable contains function pointers that point to the virtual functions in that class. There can only be one vtable per class, and all objects of the same class will share the same vtable."
So why exactly does this mean that not all classes have a vtable created for them by the compiler? Is it because somc classes don't have virtual functions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
恰恰。有些类没有 vtable,因为它们没有任何虚方法。
虚拟方法是编译器无法生成直接调用的方法,因为它根据类的实现而变化。 vtables 是一种查找表,它通过在程序运行时延迟决定调用哪个实现来解决这个问题:编译器不是生成函数调用,而是在 vtable 上生成方法查找,然后调用返回的方法。
举个例子:
这将打印
Bar
的消息。在大多数重要场景中,编译器无法提前知道调用虚拟方法的对象的类型。如上所述,vtable 通过提供统一的查找机制来查找方法实现来解决这个问题,无论对象的类型如何。vtable 指针必须存在于类的每个实例中(这需要额外内存的指针大小,可能是 4 或 8 字节),并且在程序地址空间中的某处存在一些微不足道的静态内存。这对您来说可能看起来并不多(事实上很多人都会同意),但在某些情况下这可能会很麻烦(例如内存极其有限的嵌入式系统)。为每个类提供 vtable 会违反一般的 C++ 原则,即您只需为所使用的内容付费,因此编译器在不需要时不会生成任何 vtable。
没有 vtable 会带来显着的副作用,即禁用特定时间类型的信息。如果您需要在代码中使用RTTI,您的类必须至少有一个虚拟方法。在这些情况下,惯例是将析构函数标记为虚拟的。
Precisely. Some classes don't have a vtable because they don't have any virtual methods.
Virtual methods are methods for which your compiler cannot generate a direct call because it varies depending on the implementation of the class. Vtables are a kind of lookup table that solve this problem by delaying the decision of which implementation to call during the run time of your program: instead of generating a function call, your compiler generates a method lookup on the vtable, then calls the returned method.
Take this example:
This will print
Bar
's message. In most non-trivial scenarios, your compiler cannot know in advance the type of the object on which a virtual method is called. As mentioned above, the vtable solves the problem by providing a uniform lookup mechanism to find method implementations, no matter the type of an object.A vtable pointer must exist in every instance of a class (which requires the size of a pointer of additional memory, likely to be 4 or 8 bytes), and some insignificant amount of statical memory somewhere in your program's address space. This may not seem a lot to you (and indeed many people would agree), but this can be cumbersome in certain scenarios (like embedded systems where memory is extremely limited). Having vtables for each class would violate the general C++ principle that you pay only for what you use, and therefore the compiler doesn't generate any vtable if it doesn't have to.
Not having a vtable has the notable side effect of disabling runtime type information. If you need to use RTTI in your code, your classes must have at least one virtual method. The convention is to mark the destructor virtual in these cases.
实际上,C++ 中没有任何内容要求任何类都有 vtable - 这完全是一个实现问题。然而,具有虚函数的类必须以某种方式支持多态函数调用,并且这总是需要某种类型的表/映射。该表/映射将由编译器为具有多态函数的类创建,并且可能(取决于编译器质量)为那些不具有多态函数的类创建。
Actually, nothing in C++ requires that any class has a vtable - it's entirely an implementation issue. However, a class with virtual functions must somehow support polymorphic function calls, and this will always require a table/map of some sort. This table/map will be created by the compiler for classes that have polymorphic functions, and might (depending on compiler quality) be created for those that don't.
此外,某些类没有 vtable,因为已显式删除,请参阅
__declspec(novtable)
(编译器特定)In addition, some classes don't have a vtable because is explicitly removed, see
__declspec(novtable)
(compiler specific)