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

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

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

Эл.г

class Base{
    public:
        virtual void print(){cout<<"Base Printn";}
};
class Derived:public Base{
    public:
        void print(){cout<<"Derived printn";}
};

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

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

4 ответов


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

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

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


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


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

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

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

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

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

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


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

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