我读过这个问题:C++ 虚拟类继承对象大小问题 https://stackoverflow.com/questions/57481249/c-virtual-class-inheritance-object-size-issue,并且想知道为什么虚拟继承会在类中产生一个额外的 vtable 指针。
我在这里找到一篇文章:https://en.wikipedia.org/wiki/Virtual_inheritance https://en.wikipedia.org/wiki/Virtual_inheritance
这告诉我们:
然而,在一般情况下,这个偏移量只能在运行时知道,...
我不明白这里与运行时相关的是什么。完整的类继承层次结构在编译时就已知。我了解虚拟函数和基指针的使用,但虚拟继承没有这样的东西。
有人可以解释为什么某些编译器(Clang/GCC)使用 vtable 实现虚拟继承,以及如何使用它runtime?
BTW,我也看到了这个问题:虚拟继承情况下的 vtable https://stackoverflow.com/questions/44989780/vtable-in-case-of-virtual-inheritance,但它只指向与虚函数相关的答案,这不是我的问题。
完整的类继承层次结构在编译时就已知。
确实如此;因此,如果编译器知道最派生对象的类型,那么它就知道该对象内每个子对象的偏移量。为此,不需要 vtable。
例如,如果B
and C
两者实际上都源自A
, and D
源自两者B
and C
,然后在以下代码中:
D d;
A* a = &d;
的转换来自D*
to A*
最多就是给地址添加一个静态偏移量。
然而,现在考虑一下这种情况:
A* f(B* b) { return b; }
A* g(C* c) { return c; }
Here, f
必须能够接受指向任何B
对象,包括一个B
可能是某个对象的子对象的对象D
对象或其他一些最派生类对象的对象。编译时f
,编译器不知道完整的派生类集B
.
If the B
对象是最派生的对象,那么A
子对象将位于一定的偏移量处。但如果B
对象是a的一部分D
目的?这D
对象只包含一个A
对象,并且它不能位于其通常的偏移处both the B
and C
子对象。所以编译器必须选择一个位置A
的子对象D
,然后它必须提供一种机制,以便某些带有B*
or C*
可以找出在哪里A
子对象是。这仅取决于最派生类型的继承层次结构——因此 vptr/vtable 是一种合适的机制。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)