C++面试:具有纯虚函数的类的 vtable
今天就被问到这个面试问题了!! (这是一次非常尴尬的电话采访..):
类的vtable与virtual有什么区别 函数和具有纯虚函数的类?
现在,我知道 C++ 标准没有指定任何有关 v 表的内容,甚至没有指定 v 表的存在……但是从理论上讲,答案是什么?
我脱口而出,具有纯虚函数的类可以有一个 vtable,并且纯虚函数的 vtable 条目将指向派生类的实现。这个假设正确吗?我没有从面试官那里得到肯定的答复。
假设的编译器会为仅具有纯虚函数的类创建 vtable 吗?如果类包含带定义的纯虚函数怎么办? (如所示:http://www.gotw.ca/gotw/031.htm)。
I was asked this interview question today!! (it was a really awkward telephonic interview..):
What is the difference between the vtable for a class with virtual
functions and a class with pure virtual functions?
Now, I know the C++ standard doesn't specify anything about vtables, or even the existence of a v-table ..however theoretically speaking what would the answer be?
I blurted out that the class with a pure virtual function could have a vtable and its vtable entry for the pure virtual function will point to the derived class implementation. Is this assumption correct? I did not get a positive answer from the interviewer.
Will a hypothetical compiler create a vtable for a class with only pure virtual functions? What if the class contains pure virtual functions with definitions? (as shown in : http://www.gotw.ca/gotw/031.htm).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
对于非纯虚函数,vtable 中的每个条目都将引用 final-overrider 或适应
this
的 thunk如果需要的话指针。对于纯虚函数,vtable中的条目通常包含一个指向通用函数的指针,该函数通过一些合理的消息抱怨并中止程序(在此调用的纯虚函数上下文或类似的错误消息)。是的,会的,区别在于表中存储的内容,而不是表的形状。简单来说,纯虚函数使用 NULL 指针,虚函数使用非 NULL 指针。实际上,这是一个指向通用函数的指针,该函数会在通常的编译器中抱怨并
abort()
。这不会影响vtable。 vtable 仅用于动态分派,调用永远不会动态分派到纯虚函数的定义(即,您只能通过禁用限定类型名称的动态分派来手动分派到纯虚函数:
x.base::f()
会调用base::f
,即使它是纯虚拟,但是xf() 永远不会被发送到
base::f
如果它是纯虚拟的。In the case of non-pure virtual functions, each entry in the vtable will refer to the final-overrider or a thunk that adapts the
this
pointer if needed. In the case of a pure-virtual function, the entry in the vtable usually contains a pointer to a generic function that complains and aborts the program with some sensible message (pure virtual function called within this context or similar error message).Yes, it will, the difference will be in the contents stored in the table, not in the shape of the table. In a simplistic approach, a NULL pointer for pure virtual functions, non-NULL for virtual functions. Realistically, a pointer to a generic function that will complain and
abort()
with usual compilers.This will not affect the vtable. The vtable is only used for dynamic dispatch, and a call will never be dynamically dispatched to the definition of a pure virtual function (i.e. you can only manually dispatch to the pure virtual function by disabling dynamic dispatch qualifying the name of the type:
x.base::f()
will callbase::f
even if it is pure-virtual, butx.f()
will never be dispatched tobase::f
if it is pure virtual.在这种情况下,实现几乎可以做任何事情,因为如果
您的代码最终会在上下文中调用纯虚函数
需要动态解析,它将解析为纯虚拟
函数,行为未定义。我见过几个不同的
解决方案:编译器插入一个函数的地址
终止并显示错误消息(来自
从实现质量的角度来看),编译器插入一个空值
指针,或者编译器从某个位置插入函数的地址
派生类。我还见过编译器会插入的情况
如果您提供实现,则为该函数的地址。唯一的
这个问题的正确答案是你不能指望任何特定的
行为。
An implementation can do pretty much anything in such cases, because if
your code ends up calling a pure virtual function in a context where
dynamic resolution is required, and it would resolve to a pure virtual
function, the behavior is undefined. I've seen several different
solutions: the compiler inserts the address of a function which
terminates with an error message (the preferred solution from a
quality of implementation point of view), the compiler inserts a null
pointer, or the compiler inserts the address of the function from some
derived class. I've also seen cases where the compiler will insert the
address of the function if you provide an implementation. The only
correct answer to the question is that you can't count on any particular
behavior.
我可以告诉您,Microsoft(和 MS VC++)将“纯”抽象类(仅具有纯虚函数的类)用于其 COM 接口。也许他正在谈论它。 COM 的“内部”表示是指向 vtable 的指针。 MS VC++ 中的纯抽象类以相同的方式实现,因此您可以使用它们来表示 COM 对象。显然,如果你的类有其他虚拟函数,你不能简单地用 COM vtable 覆盖它的 vtable :-)
I can tell you that "pure" abstract classes (classes with only pure virtual functions) are used by Microsoft (and MS VC++) for their COM interfaces. Perhaps he was speaking of it. The "internal" representation of a COM is a pointer to a vtable. Pure abstract classes in MS VC++ are implemented in the same way, so you can use them to represent COM objects. Clearly if you class has other virtual functions, you can't simply overwrite its vtable with the COM vtable :-)