Подтвердить что ты не робот

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

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

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

например

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

Да, это правда. Фактически, заданная дефиниция базы:

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

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

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

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

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

Ответ 4

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

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