Search code examples
c++memory-layoutvirtual-table

Why is there a top_offset in VTT implemented by gcc?


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.


Solution

  • void *top(B *b) { return dynamic_cast<void *>(b); }
    

    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 B object, or a pointer to a B subobject. The three cases need to be handled differently. The offset in the vtable is what allows this to work.