编译器是否为所有类都为其创建了Vtable?

问题描述

| 在线上有许多有关VTables的资源。他们通常对他们有相同的陈述: \“每当一个类本身包含虚函数或从父类覆盖虚函数时,编译器都会为该类建立一个vtable。这意味着并非所有类都具有由编译器为其创建的vtable。vtable包含指向以下对象的函数指针该类中的虚函数。每个类只能有一个vtable,并且同一类的所有对象将共享相同的vtable。\“ 那么,这到底为什么意味着并非所有类都具有由编译器为其创建的vtable?是因为somc类没有虚函数吗?

解决方法

精确地有些类没有vtable,因为它们没有任何虚拟方法。 虚方法是编译器无法为其生成直接调用的方法,因为它根据类的实现而有所不同。 Vtables是一种查找表,可以通过延迟在程序运行时调用哪个实现的决策来解决此问题:您的编译器不会生成函数调用,而是在vtable上生成方法查找,然后调用返回的方法。 举个例子:
class Foo
{
public:
    virtual void vMethod()
    {
        std::cout << \"Foo::vMethod was called!\" << std::endl;
    }
};

class Bar : public Foo
{
public:
    virtual void vMethod()
    {
        std::cout << \"Bar::vMethod was called!\" << std::endl;
        std::cout << \"This is not the same as Foo::vMethod.\" << std::endl;
    }
};

Foo* foo = new Bar;
foo->vMethod();
这将打印
Bar
的信息。在大多数非常规情况下,编译器无法提前知道在其上调用虚拟方法的对象的类型。如上所述,vtable通过提供统一的查找机制来查找方法实现而解决了该问题,无论对象的类型如何。 vtable指针必须存在于类的每个实例中(这需要附加内存的指针大小,可能为4或8个字节),并且程序地址空间中的某些数量的静态内存微不足道。在您看来,这似乎并不多(确实很多人都会同意),但是在某些情况下(例如内存极为有限的嵌入式系统),这可能会很麻烦。每个类都有vtable会违反一般的C ++原则,即只为使​​用的内容付费,因此,编译器无需生成任何vtable。 没有vtable具有禁用运行时类型信息的显着副作用。如果您需要在代码中使用RTTI,则您的类必须至少具有一个虚拟方法。在这些情况下,惯例是将析构函数标记为虚拟。,实际上,在C ++中,什么都不需要任何类都具有vtable-这完全是实现问题。但是,具有虚函数的类必须以某种方式支持多态函数调用,并且这将始终需要某种形式的表/映射。该表/映射将由编译器为具有多态函数的类创建,并且可能(取决于编译器质量)为那些不具有多态函数的类创建。,此外,某些类没有vtable,因为已将其明确删除,请参见
__declspec(novtable)
(特定于编译器)