Иногда это проще понять на примере:
class PureVirtual {
public:
virtual void methodA() = 0;
virtual void methodB() = 0;
};
class Base : public PureVirtual {
public:
virtual void methodA();
void methodC();
private:
int x;
};
class Derived : public Base {
public:
virtual void methodB();
private:
int y;
};
Итак, для объекта типа Derived он может выглядеть следующим образом:
------------
Known offset for vtable | 0xblah | -------> [Vtable for type "Derived"]
------------
Known offset for x | 3 |
------------
Known offset for y | 2 |
------------
С Vtable для типа "Derived"выглядит примерно так:
------------
Known offset for "methodA" | 0xblah1 | ------> methodA from Base
-------------
Known offset for "methodB" | 0xblah2 | ------> methodB from Derived
-------------
Обратите внимание, что поскольку" methodC "не был виртуальным, его вообще нет в vtable.Также обратите внимание, что все экземпляры класса Derived будут иметь указатель vtable на один и тот же общий объект vtable (поскольку они имеют одинаковый тип).
Хотя реализации для C ++ и Java немного отличаются, идеи не являютсянесовместимыми.Ключевое отличие, с концептуальной точки зрения, состоит в том, что методы Java являются «виртуальными», если они не объявлены как «окончательные».В C ++ ключевое слово «virtual» должно быть задано явно, чтобы функция была в vtable.Все, что не в vtable, будет отправлено с использованием типов времени компиляции, а не типа времени выполнения объекта.