6
votes

See here:

dynamic_cast can only be used with pointers and references to classes (or with void*). Its purpose is to ensure that the result of the type conversion points to a valid complete object of the destination pointer type.

This naturally includes pointer upcast (converting from pointer-to-derived to pointer-to-base), in the same way as allowed as an implicit conversion.

But dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type.

Why dynamic_cast is ok to use for upcast for non polymorphic types but is not OK for downcast again for non-polymorphic types?

1
I don't read, that it's OK to use it for upcasting non-polymorphic types.Torbjörn
Most likely because it needs virtual dispatch to make sure the conversion is good as it returns null_ptr if it is not. Otherwise [expr.dynamic.cast] says it has to be polymorphic for down casts.NathanOliver
But what do you think, why "polymorphic classes" is outlined for downcast only?Narek
Because the standard says so, and it says so because the i tent if dynamic_vast is to perform a checked-at-runtime cast, which is only possible if there is something to check against. The only thing to check against is the hidden polymorphism-carrying data and it only exists in polymorphic classes.n. 1.8e9-where's-my-share m.
This is a much better reference.n. 1.8e9-where's-my-share m.

1 Answers

8
votes

Converting a pointer-to-derived-type into a pointer-to-base-type can be done without knowing anything about the exact type of the object that's being pointed to, because the derived type is always an instance of the base type. That is, the conversion depends only on static information. So dynamic_cast in that direction is always okay, because it can always be done.

Using dynamic_cast to convert the other way requires knowing the actual type of the object being pointed to, because without that information there's no way to know whether the conversion is valid. For example:

Base* bp = get_base();
Derived* dp = dynamic_cast<Derived*>(bp);

In this situation, if bp in fact points to an object of type Base the conversion is not valid; if it points to an object of type Derived or a type derived from Derived, the cast is okay.

To determine the exact type of the object at runtime, the support code relies on embedded type information that is only required to be present for polymorphic types. That's why the base-to-derived cast requires a polymorphic type: it ensures that the required information is present.

Granted, the standard could have made the derived-to-base conversion invalid for non-polymorphic types, but that's a procrustean restriction; there's no good reason for prohibiting it.