In order to understand the cast system you need to dive in the object model.
The classic representation of a simple hierarchy model is containment: that if B
derives from A
then the B
object will in fact contain a A
subobject alongside its own attributes.
With this model, up-casting is a simple pointer manipulation, by an offset known at compilation time which depends from the memory layout of B
.
This is what static_cast do: a static cast is dubbed static because the computation of what is necessary for the cast is done at compile-time, be it pointer arithmetic or conversions.
However, when virtual
inheritance kicks in things tend to become a bit more difficult. The main issue is that with virtual
inheritance all subclasses share a same instance of the subobject. In order to do that, B
will have a pointer to a A
, instead of a A
proper, and the A
base class object will be instantiated outside of B
.
Therefore, it's impossible at compilation time to be able to deduce the necessary pointer arithmetic: it depends on the runtime type of the object.
Whenever there is a runtime type dependency, you need RTTI (RunTime Type Information), and making use of RTTI for casts is the job of dynamic_cast.
In summary:
- compile-time cast:
static_cast
- run-time cast:
dynamic_cast
The other two are also compile-time casts, but they are so specific that it's easy to remember what they are for... and they are smelly, so better not use them at all anyway.