Полиморфизм включения реализуется с использованием механизма виртуальных методов в C ++. Метод становится виртуальным, помещая ключевое слово virtual перед объявлением метода в классе. Когда вызывается виртуальный метод, реализация выполняемого метода выбирается на основе фактического типа объекта. Таким образом, вызов разрешается только при выполнении, а тип объекта не может быть известен априори при компиляции.
Ключевое слово virtualуказывает компилятору, что объявленный виртуальный метод может быть переопределен в производном классе. Затем достаточно создать класс и определить новый метод с той же сигнатурой (то же имя, совместимые параметры — см. Понятие ковариации). Таким образом, вызов этого метода для объекта, к которому осуществляется доступ как объект базового класса, но фактически принадлежит производному классу, приведет к вызову метода, определенного в производном классе.
В частности, обязательно использовать ключевое слово virtualперед объявлением деструктора базового класса, когда программа желает иметь возможность уничтожить объект через указатель экземпляра базового класса вместо указателя экземпляра производного класс.
Этот тип полиморфизма (полиморфизма включения) называется динамическим. Механизм перегрузки функции, который является произвольным полиморфизмом, имеет статический тип. В обоих случаях для разрешения вызова должна применяться логика (например, количество и тип параметров). В случае перегрузки функции логика полностью вычисляется во время компиляции. Это вычисление позволяет оптимизировать статический полиморфизм быстрее, чем его динамическая версия. Динамическое связывание методов в результате механизма виртуальных методов часто вызывает скрытую таблицу для разрешения вызовов, виртуальную таблицу. Эта виртуальная таблица увеличивает время, необходимое для вызова метода во время выполнения, добавляя дополнительное косвенное обращение.
Выбор между динамическим связыванием и перегрузкой (динамический и статический полиморфизм) обычно является проблемой вычислимости вызовов , часто приводящей к выбору между выразительностью и производительностью.
Несмотря на этот динамизм, следует отметить, что компилятор может «девиртуализировать» вызовы функций-членов, которые могут быть разрешены во время компиляции. В gcc, например, опция -fdevirtualize во время компиляции позволяет такую оптимизацию, если это возможно