Доступ к нему «напрямую» выполняет ту же работу, что и доступ к нему «косвенно».
Когда вы вызываете функцию на myderived
, сохраненный там указатель может указывать на некоторый объект некоторого класса, производного от derived
. Компилятор не может предположить, что это действительно объект derived
, это может быть объект другого производного класса, который переопределяет виртуальную функцию, поэтому должна выполняться диспетчеризация виртуальной функции, как в случае mybase
. В обоих случаях функция ищется в таблице виртуальных функций перед ее вызовом.
Чтобы вызвать функцию не полиморфно, не используйте указатель:
derived myderived;
myderived.func(1);
Когда вы удаляете виртуальные функции, компилятор может встроить вызов функции так, что вы в итоге получите простой цикл:
for (uint j = 0; j < 100000000; ++j)
k += i * 2;
Это намного быстрее, поскольку вы экономите накладные расходы на вызовы функций 100000000, и компилятор может даже оптимизировать цикл дальше, чем если бы в нем был вызов функции.
Обратите внимание, что разница между встроенной версией и вызовом виртуальной функции была бы намного меньше, если бы функция выполняла какую-то реальную работу. В этом примере тело функции почти не занимает времени, поэтому затраты на вызов функции перевешивают затраты на выполнение тела.