I have four classes:
class A {};
class B : virtual public A {};
class C : virtual public A {};
class D: public B, public C {};
Attempting a static cast from A* to B* I get the below error:
cannot convert from base A to derived type B via virtual base A
In order to understand the cast system, you need to dive into the object model.
The classic representation of a simple hierarchy model is containment: if B
derives from A
then the B
object will, in fact, contain an A
subobject alongside its own attributes.
With this model downcasting is a simple pointer manipulation by an offset known at compilation time, which depends on the memory layout of B
.
This is what static_cast does: 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 the same instance of the subobject. In order to do that, B
will have a pointer to an A
, instead of an 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:
static_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.
(*) As noted by @curiousguy in the comments, this only holds for downcasting. A static_cast
allows upcasting regardless of virtual or simple inheritance, though then the cast is also unnecessary.
As far as I know, you need to use dynamic_cast
because the inheritance is virtual
and you're downcasting.
You can't use static_cast
in this situation because the compiler doesn't know the offset of B relative to A at compile time. The offset must be calculated at run-time based on the exact type of the most derived object. Therefore you must use dynamic_cast
.
Yes, you have to use a dynamic_cast, but you'll have to make the base class A polymorphic, e.g. by adding a virtual dtor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With