в свою очередь произведен из
На рисунке cls3 произведен из

cls2, который в свою очередь произведен из базового класса cls1. Здесь cls2 заместил р2, но не р1, в то время как cls3 заместил обе подпрограммы.
Когда встречается вызов диспетчеризуемой подпрограммы ptr->p1(), выполняется код наподобие приведенного ниже, где мы подразумеваем, что неявный индекс — это первое поле указуемого объекта:
load RO.ptr Получить адрес объекта
load R1 ,(RO) Получить индекс указуемого объекта
load R2,&dispatch Получить адрес таблицы отправлений
add R2.R1 Вычислить адрес таблицы переходов
load R3,(R2) Получить адрес таблицы переходов
load R4,p1(R3) Получить адрес процедуры
call (R4) Вызвать процедуру, адрес которой находится в R4
Даже без последующей оптимизации затраты на время выполнения относительно малы, и, что более важно, фиксированы, поэтому в большинстве приложений нет необходимости воздерживаться от использования динамического полиморфизма. Но все же издержки существуют и применять динамический полиморфизм следует только после тщательного анализа. Лучше избегать обеих крайностей: и чрезмерного использования динамического полиморфизма только потому, что это «хорошая идея», и отказа от него, потому что это «неэффективно».
Обратите внимание, что фиксированные затраты получаются благодаря тому, что динамический полиморфизм ограничен фиксированным набором классов, порожденных из базового класса (поэтому может использоваться таблица диспетчеризации фиксированного размера), и фиксированным набором виртуальных функций, которые могут быть переопределены (поэтому размер каждой таблицы переходов также фиксирован). Значительным достижением языка C++ была демонстрация того, что динамический полиморфизм может быть реализован без неограниченного поиска во время выполнения.