Виртуальная таблица C ++ - PullRequest
       19

Виртуальная таблица C ++

20 голосов
/ 01 февраля 2010

Я читал, что многие люди пишут, что "существует класс виртуальной таблицы для класса, в котором объявлена ​​виртуальная функция".

У меня вопрос: существует ли vtable только для класса, который имеет виртуальную функцию, или он существует также для классов, производных от этого класса.

* 1005 например *

class Base{
    public:
        virtual void print(){cout<<"Base Print\n";}
};
class Derived:public Base{
    public:
        void print(){cout<<"Derived print\n";}
};

//From main.cpp 
Base* b = new Derived;
b->print();

Вопрос: Если бы не было vtable для производного класса, тогда вывод не был бы "производным выводом". Таким образом, IMO существует vtable для любого класса, в котором объявлена ​​виртуальная функция, а также для классов, унаследованных от этого класса. Это правильно?

Ответы [ 4 ]

19 голосов
/ 01 февраля 2010

Поскольку рассматривается только функциональность, специфичная для виртуальной функции, в традиционном подходе к производному классу реализации vtable потребуется отдельная версия vtable тогда и только тогда, когда , этот производный класс переопределяет хотя бы один виртуальный функция. В вашем примере Derived переопределяет виртуальную функцию print. Поскольку Derived имеет свою собственную версию print, соответствующая запись в Derived vtable отличается от записи в Base vtable. Это обычно требует отдельного vtable для Derived.

Если бы Derived вообще ничего не переопределял, формально это был бы отдельный полиморфный класс, но для правильной работы его виртуальных функций мы могли бы просто повторно использовать Base vtable для Derived. , Таким образом, технически не было бы необходимости в отдельной vtable для Derived.

Однако в практических реализациях структура данных, которую мы обычно называем «vtable», часто также содержит некоторую дополнительную информацию, специфичную для класса. Эта дополнительная информация настолько специфична для класса, что большую часть времени становится невозможным делить таблицы между различными классами в иерархии, даже если они используют один и тот же набор виртуальных функций. Например, в некоторых реализациях указатель vtable, хранящийся в каждом полиморфном объекте, указывает на структуру данных, которая также хранит так называемую «информацию RTTI» о классе. По этой причине в большинстве (если не во всех) практических реализациях каждый полиморфный класс получает свой собственный vtable, даже если указатели виртуальных функций, хранящиеся в этих таблицах, совпадают.

3 голосов
/ 01 февраля 2010

Да, ваше понимание верно. Любой класс, имеющий базу с любыми виртуальными функциями, имеет vtable.

3 голосов
/ 01 февраля 2010

Да, это правда. На самом деле, учитывая определение базы:

class derived:public base{
public:
 void print(){cout<<"derived print\n";}
};

полностью эквивалентно:

class derived:public base{
public:
 virtual void print(){cout<<"derived print\n";}
};

... потому что вы уже определили печать как виртуальную в базе.

Я бы хотел, чтобы компилятор обеспечил это ...

2 голосов
/ 01 февраля 2010

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

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

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