dynamic_cast is one of the new-style C++ typecast operators. Together with the other C++ typecast operators (const_cast, static_cast, and reinterpret_cast) it is intended to replace traditional C-style casting in C++.

The syntax for dynamic_cast, like all the C++ typecast operators, is:

dynamic_cast <typeexp> (valueexp)

Wherein typeexp is a type-expression indicating the type to cast to, and valueexp is a value-expression indicating the value to be cast. The value of the cast expression will be of type typeexp

dynamic_cast is, in my opinion, the most interesting of the C++ typecast operators, and that that most deserves its own keyword. It is intended to control typecasting between dynamic objects: that is, values whose actual type is not known until runtime. Before we explore the features of dynamic_cast, let us first ponder the woeful inadequacy of traditional C casting in such situations.

Imagine that we have a class hierarchy described here:

class Grandfather { } ;
class ParentA : public Grandfather { } ;
class ParentB : public Grandfather { } ;
class ChildA : public ParentA { } ;
class ChildB : public ParentA, ParentB { } ;

Now, consider that we have a pointer to an instance of ParentA:

ParentA *parentA = getParentA();

But, let us assume that ParentA is an abstract class. Now, that means that parentA is actually pointing to a class derived from ParentA: either ChildA or ChildB. How can one determine which? How can we get a pointer to the derived class? A silly C programmer may at this point try something like this:

ChildA *castFromParentA = (ChildA *) parentA;

However, this is gratuitously wrong on several counts. First of all, if parentA points to an instance of ChildB rather than ChildA, there is no way to determine that this cast is invalid. Secondly, this is probably incorrect even if parentA does point to a ChildA, since in C++ ancestor object have a different address from derived objects in the same instance. Anyway, you'll probably generate a bad memory reference if you try to use the resulting object.

The correct way to perform the above cast is:

ChildA *castFromParentA = dynamic_cast <ChildA *> ( parentA );

If parentA does indeed point to an instance of ChildA, then castFromParentA will point to it. If parentA points to a ChildB, then castFromParentA will contain NULL. This complex operation is reasonably expensive at runtime, and shouldn't ever really be a necessary regular part of your code, but sometimes it can get you out of a tight corner. Ideally, according to object-oriented doctrine, a caller shouldn't care what the actual type of an object is: all derived classes should behave rationally in their particular role. Unfortunately, the rigors of modern groupthink development make this true less of the time than it should be, and thus dynamic_cast has its klugey purpose.

A somewhat more complex situation arises here:

ParentA &parentARef = getParentARef();
ChildA &childARef = dynamic_cast < ChildA > ( parentA );

Now, in this situation, how can you check for a failed cast? Clearly, dynamic_cast can't return NULL, since NULL references are illegal. What will happen, if, for whatever reason, parentA cannot be cast to ChildA, is that dynamic_cast will throw a bad_cast exception, which, if not caught, will abnormally terminate the program.

Are you still awake? I'm telling you this because you care.

dynamic_cast has other uses, as well, mostly involving moving around an inheritance tree. In some cases, to get a particular class from an instance, multiple uses of dynamic_cast are ncessary. For example, because ParentA and ParentB inherit from Grandfather non-virtually, every instance of ChildB contains two instances of Grandfather. We can acquire either of these by first casting a ChildB to either ParentA or ParentB, and then casting the result to Grandfather.

Note that the syntax for C++'s typecast operators is similar to the syntax for instantiating and calling a function template. This allows you to declare your own methods that behave like casting operators, but adapted to your own nefarious ends. To wit:

template <typename Target,typename Source>
Target &my_cast(const Source &);

Which can then be called like this:

A a;
B b;
a = my_cast <A> (b);

This will not work under antiquated or otherwise silly compilers.

Sorry if this write-up was unduly long-winded, confusing, or boring. I try to be thorough. If you have any comments, please let me know. Thanks.

Log in or register to write something here or to contact authors.