I am interested in understanding how, generally speaking, the runtime checks whether a base class actually points to a derived class when using dynamic_cast to apply a downcast. I know that each virtual table of a polymorphic class contains RTTI too (in the form of type_info pointers).
-
The compiler or the runtime? The compiler doesn't need RTTI – Alan Birtles Jan 26 '22 at 15:26
-
The runtime, thanks for the correction – user15532034 Jan 26 '22 at 15:26
-
The runtime uses the RTTI to traverse the graph to see if the type pointed to can be downcast to the type given. The traversal accounts for multiple inheritance. Profiling can determine if the performance is of concern. – Eljay Jan 26 '22 at 15:37
1 Answers
Every compiler is going to have slight differences in implementation, but I'm going to use MSVC as a reference as they easily supply the source with VS.
You can view all of the details on how MSVC does it by going to your Visual Studio installation and going to /Community/VS/Tools/MSVC/${VERSION}/crt/src/vcruntime/rtti.cpp
The compiler will internally convert dynamic_cast
's to call the function __RTDynamicCast
(or __RTCastToVoid
if try to cast to a void*
), this will take in the RTTI info for the target type and the source type. The key element in the _RTTITypeDescriptor
structure is the fully decorated name. It will then dispatch to one of 3 different implementations depending on whether the input type has single inheritance, multiple inheritance, or virtual inheritance.
For single inheritance FindSITargetTypeInstance
will walk through the the list of base class types, and if it finds a match by pointer comparison it will return the class descriptor. If it fails to find a match by pointer comparison it will try again using string comparisons.
For multiple inheritance FindMITargetTypeInstance
will walk the class hierarchy in a depth-first, left-to-right order until it has seen the descriptor for both the source type and the target type. Every comparison is done through TypeidsEqual
which will first try to do a pointer comparison, but will immediately fallback to string comparison, this differs from single inheritance in that single inheritance did this in 2 separate loops as it is likely the pointers would match.
For virtual inheritance FindVITargetTypeInstance
will walk the entire class hierarchy. This is the slowest of the three as it cannot exit early due to potential diamond problems. Every comparison is done through TypeidsEqual
.
Once the descriptor for the type has been found it will use that to calculate an offset from the source pointer to the target pointer.
Overall the code is fairly simple and incredibly well documented, though I did leave out some nuances like checking to see if the base class was publicly derived, or distinguishing between down-casts, up-casts, and cross-casts.

- 1,973
- 3
- 19
- 28
-
1This was the most detailed and informative answer I could wish for, thank you! – user15532034 Jan 26 '22 at 16:45