所有类都有编译器为它们创建的Vtable吗?

xar*_*rzu 6 c++ vtable

有关VTables的在线资源很多.他们通常对此有相同的陈述:

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

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

zne*_*eak 7

正是.有些类没有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();
Run Code Online (Sandbox Code Playgroud)

这将打印出来Bar的消息.在大多数非平凡的场景中,编译器无法事先知道调用虚方法的对象的类型.如上所述,vtable通过提供统一的查找机制来找到方法实现来解决问题,无论对象的类型如何.

vtable指针必须存在于类的每个实例中(这需要额外内存指针的大小,可能是4或8个字节),以及程序地址空间中某些不重要的静态内存.这对你来说似乎并不是很多(事实上很多人会同意),但在某些情况下(例如内存非常有限的嵌入式系统),这可能很麻烦.拥有每个类的vtable会违反您只为所使用的内容付费的一般C++原则,因此如果不需要,编译器不会生成任何vtable.

不具有虚表具有禁用的显着副作用ř IME YPE 载文信息.如果需要在代码中使用RTTI,则类必须至少具有一个虚方法.惯例是在这些情况下将析构函数标记为虚拟.


小智 5

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

  • 您是否知道单个C++编译器*曾经*,无论质量有多糟糕,为没有多态函数的类创建了vtable(或其任何模拟)? (3认同)