Виртуальная функция позволяет реализовать полиморфизм во время выполнения. Когда вызывается виртуальная функция объекта, фактическая вызываемая версия функции определяется типом объекта, на который указывает указатель или ссылка, а не типом указателя или ссылки.
Для реализации этого механизма компилятор добавляет к каждому объекту класса с виртуальными функциями скрытый указатель — vptr (virtual pointer). Этот указатель указывает на таблицу виртуальных функций — vtable (virtual table).
vtable — это статическая таблица, общая для всех объектов данного класса, которая содержит указатели на реализации виртуальных функций этого класса. Для производного класса, который переопределяет виртуальные функции, его vtable содержит указатели на переопределенные версии. Если производный класс не переопределяет виртуальную функцию, его vtable содержит указатель на версию из базового класса.
При вызове виртуальной функции через указатель или ссылку компилятор генерирует код, который:
c
Ключевое слово virtual перед объявлением функции в базовом классе делает ее виртуальной. Ключевое слово override в производном классе явно указывает, что функция переопределяет виртуальную функцию из базового класса (хорошая практика для избежания ошибок).
Виртуальный деструктор в базовом классе важен для корректного освобождения ресурсов, когда объект производного класса удаляется через указатель на базовый класс.
c
Если деструктор в Base не виртуальный, при удалении delete obj; будет вызван только деструктор Base, что приведет к утечкам памяти или другим проблемам, если Derived имеет свои ресурсы.