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

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

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

например,

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 для любого класса, которому объявили виртуальную функцию и также в классах, наследовавшихся тому классу. Это корректно?

20
задан curiousguy 9 February 2017 в 21:22
поделиться

4 ответа

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

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

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

19
ответ дан 30 November 2019 в 00:47
поделиться

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

3
ответ дан 30 November 2019 в 00:47
поделиться

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

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

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

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

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

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

3
ответ дан 30 November 2019 в 00:47
поделиться

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

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

2
ответ дан 30 November 2019 в 00:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: