Вот подробное описание VTT в ответе с наибольшим количеством голосов. Но ответ не объясняет, почему существует top-offset
в VTT.
С моей точки зрения, когда мы down_cast
base
указатель на derived
указатель,компилятор уже знает offset
необходимо настроить во время компиляции(когда нет виртуального деривации), поэтому нет необходимости хранить top_offset
в ситуации ниже:
class A {
public:
int a;
};
class B {
public:
int b;
virtual void w();
};
class C : public A, public B {
public:
int c;
};
В этом случае объекты типа C размещаются следующим образом (числа предполагают 32-разрядные указатели):
+-----------------------+
| 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 | +-----------------------+
+----------+
Почему есть top_offset
в VTT при такой ситуации? я думаю top_offset
а также virtual base offset
нужны только при виртуальном наследовании.
void *top(B *b) { return dynamic_cast<void *>(b); }
Компилятор не может определить во время компиляции, что является правильным смещением. Эта функция может быть вызвана с нулевым указателем, указателем на завершенный B
объект или указатель на B
субобъект. Три случая должны быть обработаны по-разному. Смещение в vtable — то, что позволяет этому работать.
Других решений пока нет …