【问题标题】:Do all classes have a Vtable created for them by the compiler?编译器是否为所有类创建了一个 Vtable?
【发布时间】:2011-04-18 23:12:12
【问题描述】:

网上有很多关于 VTable 的资源。他们通常有相同的声明:

"每当一个类本身包含虚函数或覆盖父类的虚函数时,编译器都会为该类构建一个虚表。这意味着并非所有类都有编译器为它们创建的虚表。 vtable 包含指向该类中的虚函数的函数指针。每个类只能有一个 vtable,并且同一类的所有对象将共享同一个 vtable。"

那么,为什么这意味着并非所有类都有编译器为它们创建的 vtable?是不是因为 somc 类没有虚函数?

【问题讨论】:

    标签: c++ vtable


    【解决方案1】:

    没错。有些类没有 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 具有显着的副作用,即禁用 runtime type i信息.如果您需要在代码中使用 RTTI,您的类必须至少有一个虚拟方法。惯例是在这些情况下将析构函数标记为虚拟。

    【讨论】:

      【解决方案2】:

      实际上,C++ 中的任何内容都不需要任何类具有 vtable - 这完全是一个实现问题。但是,具有虚函数的类必须以某种方式支持多态函数调用,这总是需要某种表/映射。该表/映射将由编译器为具有多态函数的类创建,并且可能(取决于编译器质量)为那些没有的类创建。

      【讨论】:

      • 你知道一个 C++ 编译器曾经,不管质量有多差,它为没有多态函数的类创建 vtables(或其任何类似物)?
      • 我不知道,这是有充分理由的:要实现extern "C",C++ 编译器必须已经支持没有 vtable 的结构。还不如高效,只在需要时创建 vtables。
      【解决方案3】:

      另外,有些类没有 vtable 因为被显式删除,参见__declspec(novtable)(特定于编译器)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-24
        • 1970-01-01
        • 1970-01-01
        • 2017-01-16
        • 1970-01-01
        相关资源
        最近更新 更多