为什么即使不涉及虚拟功能,虚拟继承也需要vtable? [英] Why does virtual inheritance need a vtable even if no virtual functions are involved?

查看:104
本文介绍了为什么即使不涉及虚拟功能,虚拟继承也需要vtable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了以下问题: C ++虚拟类继承对象大小问题,并且想知道为什么虚拟继承会在类中导致附加的vtable指针.

I read this question: C++ Virtual class inheritance object size issue, and was wondering why virtual inheritance results in an additional vtable pointer in the class.

我在这里找到了一篇文章: https://en.wikipedia.org/wiki/Virtual_inheritance

I found an article here: https://en.wikipedia.org/wiki/Virtual_inheritance

告诉我们:

但是,通常只能在运行时知道此偏移量,...

However this offset can in the general case only be known at runtime,...

我在这里不了解与运行时相关的内容.完整的类继承层次结构在编译时就已为人所知.我了解虚函数和基指针的用法,但是虚继承没有这种东西.

I don't get what is runtime-related here. The complete class inheritance hierarchy is already known at compile time. I understand virtual functions and the use of a base pointer, but there is no such thing with virtual inheritance.

有人可以解释为什么某些编译器(Clang/GCC)使用vtable实现虚拟继承以及在运行时期间如何使用它吗?

Can someone explain why some compilers (Clang/GCC) implement virtual inheritance with a vtable and how this is used during runtime?

顺便说一句,我也看到了这个问题:在虚拟继承的情况下是vtable ,但它仅指向与虚函数相关的答案,这不是我的问题.

BTW, I also saw this question: vtable in case of virtual inheritance, but it only points to answers related to virtual functions, which is not my question.

推荐答案

在编译时就已经知道完整的类继承层次结构.

The complete class inheritance hierarchy is already known in compile time.

真的吗?因此,如果编译器知道派生程度最高的对象的类型,则它知道该对象内每个子对象的偏移量.为此,不需要vtable.

True enough; so if the compiler knows the type of a most derived object, then it knows the offset of every subobject within that object. For such a purpose, a vtable is not needed.

例如,如果BC都实际上是从A派生的,而D是同时从BC派生的,则在下面的代码中:

For example, if B and C both virtually derive from A, and D derives from both B and C, then in the following code:

D d;
A* a = &d;

D*A*的转换最多是在地址上添加静态偏移量.

the conversion from D* to A* is, at most, adding a static offset to the address.

但是,现在考虑这种情况:

However, now consider this situation:

A* f(B* b) { return b; }
A* g(C* c) { return c; }

在这里,f必须能够接受指向任何B对象的指针,包括B对象,该对象可能是D对象或某些其他派生最多的类对象的子对象.编译f时,编译器不知道B的完整派生类集.

Here, f must be able to accept a pointer to any B object, including a B object that may be a subobject of a D object or of some other most derived class object. When compiling f, the compiler doesn't know the full set of derived classes of B.

如果B对象是派生程度最高的对象,则A子对象将位于某个偏移处.但是,如果B对象是D对象的一部分,该怎么办? D对象仅包含一个A对象,并且不能以与,,BC子对象相同的偏移量定位.因此,编译器必须为DA子对象选择一个位置,然后必须提供一种机制,以便某些带有B*C*的代码可以找出A子对象的位置. .这完全取决于大多数派生类型的继承层次结构-因此,vptr/vtable是合适的机制.

If the B object is a most derived object, then the A subobject will be located at a certain offset. But what if the B object is part of a D object? The D object only contains one A object and it can't be located at its usual offsets from both the B and C subobjects. So the compiler has to pick a location for the A subobject of D, and then it has to provide a mechanism so that some code with a B* or C* can find out where the A subobject is. This depends solely on the inheritance hierarchy of the most derived type---so a vptr/vtable is an appropriate mechanism.

这篇关于为什么即使不涉及虚拟功能,虚拟继承也需要vtable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆