c++ dynamic_cast
class CBase { };
class CDerived: public CBase { };
CBase b;
CBase* pb;
CDerived d;
CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic开发者_JAVA技巧_cast<CDerived*>(&b); // wrong: base-to-derived
I know the "base to derived " cast is wrong. But what is the inside reason of it? What is logical reason inside? It's hard to remember this without more explanation I guess. thank you!
First, CBase
must be polymorphic in order for you to use dynamic_cast
here (that is, it must have at least one virtual
member function). Otherwise, you can't use dynamic_cast
.
That said, the cast of &b
to CDerived*
is not wrong: pd
will be a null pointer.
dynamic_cast
has the useful property that when the cast fails (that is, if the object pointed to by the pointer isn't of the target type), it yields a null pointer. This allows you to test the actual type of an object. For example:
CBase b;
CDerived d;
CBase* pb = &b;
CBase* pd = &d;
CDerived* xb = dynamic_cast<CDerived*>(pb); // xb is null!
CDerived* xd = dynamic_cast<CDerived*>(pd); // xd points to d!
Your code would have been incorrect if you had used static_cast
, since it casts without performing any runtime type check, which means there is no way to test whether the cast succeeded. If you ever need to cast down a class hierarchy and you don't know for certain whether the object is of the derived type to which you are trying to cast, you must use dynamic_cast
.
For the derived to base conversion, you don't need (and generally don't want) to specify a cast explicitly at all:
CDerived d;
CBase *pb = &d; // perfectly fine
The base to derived cast isn't really wrong, though you'd generally prefer to avoid it. The reason behind that is fairly simple: a pointer to base could be pointing to an actual base object or anything derived from it. If you're going to down-cast like this, you generally need to check whether the conversion succeeded. In the specific case you've given, it won't succeed, so what gets assigned (the result of the dynamic_cast
) will simply be a null pointer.
Most of the time, you'd prefer to specify a complete interface to objects of the class in the base class, so you rarely have much need for downcasts.
A derived class can have more "behaviors" than the base class. More member functions, more member data, etc. If you cast a base class to a derived class, and then try to treat it as a derived class, you'll try to make it do things it can't do. Because you are trying to make an instance of the base class do things only the derived class knows how to do.
pd
is a pointer of type CDerived*
. So, pd
pointing object needs to have two sub-objects involved ( i.e., base & derived ). But with this statement -
pd = dynamic_cast<CDerived*>(&b);
Here ,pd
is pointing to only a base sub-object. There is no partial way of pointing to sub-objects. So, it is wrong.
精彩评论