In the last article, we looked at the std:is_base_of<T1, T2> type trait. One question that a reader asked since that article appeared is “How does is_base_of<> differ from the dynamic_cast<> operator?”
Good question! In today’s post let me try to address the key differences between the two.
I am not going to cover the dynamic_cast<> operator in detail here. I urge you to go through the primary reference.
One of the common uses of dynamic_cast<> operator is to “safely” cast a pointer to base class type to a pointer to derived class type, provided it is valid. This might require the use of run-time type information (RTTI).
Contrast this with is_base_of<>. This works with type names and not object references. To get a better idea, feel free to go through the earlier post.
Let us look at 4 different cases comparing dynamic_cast<> and is_base_of<>.
Case -1: Working with Classes
dynamic_cast<> can only work with class types, not primitive types. That is not a restriction in the case of is_base_of<>. See the following example:
You can see that dynamic_cast<> will not accept a non-class argument (line 15).
Case-2: Non-polymorphic Class Hierrachy
dynamic_cast<> expects the argument to refer to a polymorphic class class, i.e., one that has at least one virtual function. The example below illustrates this point.
is_base_of<> does not have this limitation.
Case-3: Polymorphic Class Hierarchy
This is the common use case for dynamic_cast<> operator. Go through the following example.
This shows how dynamic_cast<> uses RTTI to convert a pointer from base class to derived class pointer. In the case of invalid conversion, it returns NULL.
The type trait is_base_of<> works with types and not actual objects.
Case-4: Class Hierarchy with Twists!
As the final example, let us consider a class hierarchy that uses protected derivation and also multiple derivation of a common base class.
Notice that class R is derived from Q using “protected” mode. Due to this, methods outside of R (global functions or methods of any class not derived from R) cannot access any member of Q via R instance. Interestingly, because of the non-public derivation, dynamic_cast<> fails in line 18 by returning NULL.
Likewise, class S derives from P twice, via Q and R. This results in S object having two instances of P inside it. That is why, in lines 39-40, we first convert to void * then convert to P *. Of course, we get a run-time exception when we convert back to derived class through dynamic_cast<>.
It is possible to consider some minor variations of the above examples, but I think you now have a good understanding of the difference between dynamic_cast<> and is_base_of<>.
The example programs can be downloaded from here. I used Visual Studio 2019 (64 bit), Version 16.5.4 to test these examples.
Have a nice weekend!
Recent Comments