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.
There is no way for the compiler to determine at compile time what the correct offset is. This function may be called with a null pointer, a pointer to a complete
Bobject, or a pointer to aBsubobject. The three cases need to be handled differently. The offset in the vtable is what allows this to work.