如果我像这样创建一个非常简单的类:
class A
{
public :
virtual void foo()
{
}
};
(没有虚拟析构函数)编译器会创建 vtable 吗?或者现代编译器是否足够聪明以识别这种情况(这可能是错误的复制和粘贴)并且不为此类类添加虚拟表?
v-table 是一个实现细节。将 v-tables 用于虚函数的编译器将为此类创建一个。那些不会,不会。
编译器不能确定该类不是在另一个编译单元中派生的,因此它必须确保调用正确地依赖于实例的运行时类型。
如果它使用 vtable 来解析虚拟调用,则将创建一个 vtable。如果使用另一个实现,则将使用该机制。
旧版本:将创建一个 vtable,因为编译器无法确定该类不会在另一个编译单元中派生。
答案是编译器必须生成一个 v-table。要了解为什么考虑:
class B : public A
{
void foo() { do something interesting }
}
在其他地方:
void bar (A& obj)
{
obj.foo()
}
可以肯定地将 B 类型的对象传递给bar()
并且B::foo()
将调用。对所有多态类总是有一个虚拟析构函数是一种很好的编程习惯,因为它允许多态删除 A。在我们的例子中,obj
是类型B
void bar2 (A& obj)
{
delete obj;
}
可能不会像预期的那样表现,因为 B 的析构函数永远不会被调用。