dynamic_cast
helps you check the validity while performing downcasting.
It returns a NULL or throws an exception(std::bad_cast
for References)if the pointer or the reference cannot be safely downcasted.
Would you use dynamic cast in a frequently run method? Does it have a large overhead?
dynamic_cast
does use some additional RTTI(Run Time Type Information)
for determining the validity of cast. So there is an overhead for sure. Typically, a pointer to typeinfo
of the type
will be added to the virtual table
. I say typically, because virtual mechanism itself is compiler implementation dependant detail(may vary for different compilers).
You will have to profile your code using some good profiling tools to determine if calling dynamic_cast
repeatedly reduces the performance of your code.
What exactly IS the pointer returned by dynamic_cast
. A pointer to the same address? a pointer to a different instance?
It is easier to understand when instead of analyzing downcasting with dynamic_cast
we analyze upcasting. Given a type base
and another type derived
that inherits from base
, the derived
type will contain a subobject of type base
. When a pointer to a derived
object is upcasted to a pointer to base
, the result of the operation will be the address of the base
subobject inside derived
. Performing a dynamic_cast
reverts that operation, and returns a pointer to the derived
object that contains a base
subobject in the address passed as argument (static_cast
does the same, but it will apply the possible offset without actually checking the runtime type).
In the simplest case, with single (non-virtual) inheritance the derived
subobject will be aligned base
, but in the event of multiple inheritance, that will not be the case:
struct base {
int x;
virtual void foo() {}
};
struct another_base {
virtual void bar() {}
};
struct derived : base, another_base {};
int main() {
derived d;
base * b = &d; // points to the base subobject inside derived
another_base * o = &d; // points to the another_base subobject inside derived
std::cout << std::boolalpha
<< ( static_cast<void*>(b) == dynamic_cast<derived*>(b) ) << "\n"
<< ( static_cast<void*>(o) == dynamic_cast<derived*>(o) ) << std::endl;
}
The program will print true
, false
. Note that you have to explicitly cast one of the pointers to void*
if you want to compare them, or else the compiler will perform an implicit upcast the downcasted pointer.