На самом деле, я не вижу никакой эффективной разницы в использовании static_cast
и dynamic_cast
здесь.Во-первых, если вы вызываете виртуальную функцию через приведенный указатель, все последующие вызовы будут иметь тот же эффект - они будут вызывать динамическую диспетчеризацию :
auto v0 = p->f();
auto v1 = static_cast<B*>(p)->f();
auto v2 = dynamic_cast<B*>(p)->f();
dynamic_cast
может добавить некоторые накладные расходы, но наблюдаемый эффект будет таким же.А именно.Будет вызван B::f
(если он переопределен).
Что касается не виртуальных функций из производного класса, вам необходимо привести:
auto x1 = static_cast<const B*>(p)->g();
auto x3 = dynamic_cast<const B*>(p)->g();
Еслиэти приведения недействительны, вы получите неопределенное поведение в обоих случаях.Если они действительны, будет эффективно то же самое.Еще раз, с некоторыми дополнительными издержками dynamic_cast
.
Обратите внимание, что, IMO, в вашей программе не оптимизировано dynamic_cast
.Вы можете наблюдать два dynamic_cast
вызова в вашей сборке, и у вас есть две различные формы dynamic_cast
в вашем коде.Я предполагаю, что компилятор делает dynamic_cast<B*>
только один раз и использует результат 3 раза.
Обратите внимание, что вы можете обойти динамическую диспетчеризацию, вручную выбрав, какую f
вы хотите вызвать, используя следующий синтаксис:
auto y1 = static_cast<B*>(p)->A::f();
auto y2 = static_cast<B*>(p)->B::f();
Или с dynamic_cast
точно так же.
Демонстрационная версия: https://wandbox.org/permlink/CZRLPWxHjSMk8dFK.