Here is a detailed description of VTT in the top-voted answer.But the answer does not explain why is there a top-offset
in the VTT.
From my point of view,when we down_cast
a base
pointer to derived
pointer,the compiler already knows the offset
needed to be adjusted in compile time(when there is no virtual derivation) ,so there is no need to store a top_offset
in situation below:
class A {
public:
int a;
};
class B {
public:
int b;
virtual void w();
};
class C : public A, public B {
public:
int c;
};
In this case, objects of type C are laid out like this (numbers assuming 32-bit pointers):
+-----------------------+
| 0 (top_offset) |//why?
+-----------------------+
c --> +----------+ | ptr to typeinfo for C |
| vtable |-------> +-----------------------+
+----------+ | A::v() |
| a | +-----------------------+
+----------+ | -8 (top_offset) |//why?
| vtable |---+ +-----------------------+
+----------+ | | ptr to typeinfo for C |
| b | +---> +-----------------------+
+----------+ | B::w() |
| c | +-----------------------+
+----------+
Why is there a top_offset
in VTT under such situation? I think the top_offset
and virtual base offset
are only needed in virtual inheritance.
dynamic_cast
if you inherit virtually fromC
. – Schoonmakervirtual base offset
. – HabitedB
will be compiled to use one specific layout that cannot change at runtime. And that layout includes the top offset. – SagittaB
by reference and uses anything in the vtable, if it doesn't know whether it's plainB
orB
-in-C
, how could it use the vtable if it couldn't know the vtable layout? – SagittaA::v()
? – Dentist