vtable为带有纯虚函数的类

C++ Interview: vtable for a class with a pure virtual function

本文关键字:函数 vtable      更新时间:2023-10-16

今天面试中有人问我这个问题!(这真是一次尴尬的电话面试…):

类的虚函数表与虚函数表有什么区别函数和类与纯虚函数?

现在,我知道c++标准没有指定任何关于变量表的东西,甚至没有指定v表的存在。然而,从理论上讲,答案是什么?

我脱口而出,具有纯虚函数的类可以有一个虚值表,其纯虚函数的虚值表条目将指向派生类的实现。这个假设正确吗?我没有从面试官那里得到肯定的答复。

假设的编译器会为一个只有纯虚函数的类创建一个虚函数表吗?如果类包含带定义的纯虚函数怎么办?(如:http://www.gotw.ca/gotw/031.htm)。

在非纯虚函数的情况下,虚函数表中的每个表项将引用final-overriderthunk,该在需要时适应this指针。在纯虚函数的情况下,虚函数表中的项通常包含一个指向泛型函数的指针,该泛型函数会用一些合理的消息(在此上下文中调用的纯虚函数或类似的错误消息)报错并终止程序。

假设的编译器会为一个只有纯虚函数的类创建一个虚函数表吗?

是的,不同之处在于表中存储的内容,而不是表的形状。在一个简单的方法中,NULL指针用于纯虚函数,非NULL指针用于虚函数。实际上,一个指向泛型函数的指针在通常的编译器中会报错和abort()

如果类包含带定义的纯虚函数怎么办?

这不会影响虚表。虚函数表只用于动态调度,调用永远不会被动态调度到纯虚函数的定义(即,你只能通过禁用动态调度来限定类型的名称来手动调度到纯虚函数:x.base::f()将调用base::f,即使它是纯虚,但x.f()永远不会被调度到base::f,如果它是纯虚的。

在这种情况下,实现几乎可以做任何事情,因为如果你的代码最终会在一个上下文中调用一个纯虚函数动态解析是必需的,它将解析为纯虚的函数时,行为未定义。我见过几个不同的解决方法:编译器插入一个函数的地址以错误消息结束(来自从实现质量的角度来看),编译器插入一个空值指针,或者编译器插入函数的地址派生类。我也见过编译器插入如果您提供了实现,则该函数的地址。唯一的这个问题的正确答案是你不能指望任何特定的的行为。

我可以告诉你,"纯"抽象类(只有纯虚函数的类)被Microsoft(和msvc++)用于它们的COM接口。也许他是在说这件事。COM的"内部"表示是指向虚参表的指针。vc++中的纯抽象类以同样的方式实现,所以你可以用它们来表示COM对象。显然,如果类有其他虚函数,就不能简单地用COM虚表覆盖它的虚表:-)