For a project of mine, I finally need to work with my first polymorphic class (except std::cout).
I am researching how to be sure I have 100% devirtualized calls at least in some cases.
Is this code legal and viable?
How slow will be the dynamic_cast? If I pay it once in the constructor, then I will be able always to use class B directly, so it sounds as good practice?
Will C style cast be fast after that or I must store pointer to B?
struct A{
virtual void x();
};
struct B : A{
void x() override;
};
struct X{
A *a;
bool fB;
X(A &a) : a(&a), fB( dynamic_cast<B *>(&a) ){}
void f(){
if (fB){
((B*)a)->x();
}else{
a->x();
}
}
};
void fn(A &a){
X x(a);
x.f();
}
int main(){
B b;
X x(b);
x.f();
}
With your existing code, I actually would hope your compiler optimizes away the if-statement and your cast as this is pesimizing the code.
From the compiler's point of view, your code-base could be looking the following way:
So, when is sees your cast and function call:
static_cast<B*>(a)->x()it still has to access the same virtual table as to when callinga->x()as there could be a potential class C. (Please note that I use static_cast, as c-style casts are sources for bugs)If you want to get a direct call to B, you better make the method or class
final. Another good approach is using profile guided optimization, in which case, they often compare the vtable pointers.To answer your side questions?
My advice, especially since you are new to C++: Don't do this or any other manual optimizations. Compilers can do a lot for you. Every manual optimization causes extra maintenance afterward, only use these kinds of tricks if you actually have a performance problem.
Oh, and if you want to know what the actual assembly code it, you can experiment at compiler explorer