Виртуальный стол / диспетчерская таблица - PullRequest
14 голосов
/ 07 июля 2011

Из того, что я знаю о CPP, у каждого класса есть свой vtable.

Однако эта ссылка на википедию упоминает:

Таблица отправки объекта будет содержать адреса объекта динамически связанные методы. метод вызовы выполняются путем извлечения адрес метода из объекта диспетчерский стол. Таблица отправки одинаково для всех объектов, принадлежащих тот же класс, и, следовательно, обычно разделяется между ними.

Может кто-нибудь, пожалуйста, пролить немного света.

Спасибо!

Ответы [ 4 ]

13 голосов
/ 07 июля 2011

Иногда это проще понять на примере:

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, будет отправлено с использованием типов времени компиляции, а не типа времени выполнения объекта.

6 голосов
/ 07 июля 2011

Да, виртуальные методы обрабатываются компилятором и средой выполнения по-разному.

Java: Все методы в java по умолчанию являются виртуальными.Это означает, что любой метод может быть переопределен при использовании в наследовании, если только этот метод не объявлен как окончательный или статический.

Из спецификации VM ,

Виртуальная машина Java не требует какой-либо конкретной внутренней структуры для объектов.Отметим, что в книге указано: В некоторых реализациях Sun виртуальной машины Java ссылка на экземпляр класса представляет собой указатель на дескриптор, который сам является парой указателей: один на таблицу, содержащую методы объекта и указательобъекту Class, представляющему тип объекта, а другой - памяти, выделенной из кучи для данных объекта.


C ++:

Всякий раз, когда функция-член класса объявляется как виртуальная, компилятор создает в памяти виртуальную таблицу, которая содержит все указатели функций, которые объявлены как виртуальные в этом классе.Это включает полиморфизм во время выполнения (т.е. обнаружение желаемой функции во время выполнения).Таблицы виртуальных функций также имеют дополнительный указатель в объекте на vtable.Поскольку этот дополнительный указатель и виртуальная таблица увеличивают размер объекта, разработчик класса должен быть осторожен с объявлением функций виртуальными.

Последовательность событий при вызове метода для указателя базового объекта:

  • Получить указатель vtable (этот указатель vtable указывает на начало vtable).
  • Получить указатели функций в vtable с использованием смещения.

Косвенный вызов функции через указатель vtable.

2 голосов
/ 07 июля 2011

Каждый класс, имеющий виртуальные функции (т.е. в Java это просто «каждый класс»), имеет свой собственный vtable.Каждый объект скрыл ссылку на свой класс vtable.Итак, объекты одного и того же класса имеют идентичные ссылки.

Когда вы выполняете вызов виртуального метода, компилятор обычно делает поиск:

obj.method(args);

переводится во что-то

obj.vtable[idx_method](obj, args);

Иногда, если компилятор может определить конкретный тип объекта, он может генерировать статический вызов вместо виртуального.Таким образом, код

MyObject obj(ctor_args);
....
obj.method(args);

можно перевести в

MyObject_method(obj, args);

, который обычно выполняется быстрее, чем виртуальный вызов.

0 голосов
/ 07 июля 2011

Эта цитата указывает на то, что у каждого объекта есть таблица диспетчеризации, которая может быть общей для класса, поскольку они одинаковы для всех экземпляров одного и того же класса.IE Каждый класс имеет свой собственный vtable.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...