Что такое виртуальная функция в C++
Что проверяют
Понимаете ли вы механизм динамической диспетчеризации и её цену, а не только ключевое слово. Вопрос базовый, поэтому ждут точности: когда вызов разрешается при компиляции, когда во время выполнения, и что при этом происходит с объектом в памяти.
Как отвечать
Виртуальная функция объявлена в базовом классе со словом virtual и может быть переопределена в производном. Вызов через указатель или ссылку на базовый класс уходит в реализацию, соответствующую динамическому типу объекта, а не типу указателя.
Механика: класс с виртуальными функциями получает таблицу указателей на функции, а каждый объект получает скрытый указатель на эту таблицу. Отсюда две цены: объект вырастает на размер указателя, а вызов становится косвенным и обычно не встраивается.
struct Base {
virtual ~Base() = default;
virtual void show() const;
};
struct Derived final : Base {
void show() const override;
};Обязательно скажите про виртуальный деструктор: удаление объекта через указатель на базу без него даёт неопределённое поведение. Дальше полезно назвать override, который заставляет компилятор проверить факт переопределения, final, который разрешает девиртуализацию, и чисто виртуальную функцию, задающую интерфейс и делающую класс абстрактным.
Где спотыкаются
Вызывают виртуальную функцию из конструктора или деструктора и ждут версию наследника. Пока выполняется конструктор базы, динамический тип объекта ещё базовый, и вызов уйдёт в базовую реализацию, а для чисто виртуальной это прямой путь к падению.
Передают полиморфный объект по значению и теряют производную часть. Срезка бесшумна: код компилируется, а вызывается базовое поведение. Полиморфизм живёт только через указатель или ссылку.
Забывают, что значения аргументов по умолчанию подставляются по статическому типу, а тело выбирается по динамическому. Переопределение с другим значением по умолчанию даёт тело наследника, в которое приехало значение из базы, и поведение выглядит необъяснимым.