Home > Blogs > 30 C++ Tips in 30 Days: Tip # 22 using dynamic_cast safely

30 C++ Tips in 30 Days: Tip # 22 using dynamic_cast safely

By  Dec 10, 2007

Topics: Programming, C/C++

Operator dynamic_cast has two flavors: one that operates on pointers and one that operates on references. While the reference version seems more appealing, it has some dark sides of which many programmers aren't aware. Therefore, I still prefer the pointer version.

The following listing demonstrates the two forms of dynamic_cast:

derived = dynamic_cast<derived&> (baseobj);
derived *p= dynamic_cast<derived*> (&baseobj); 

The first form seems cleaner and frees the programmer from messing with pointers. However, it has a serious design flaw -- it completely ignores exceptions! Remember, unlike other cast operators which take place at compile-time, dynamic_cast operates at runtime. When it fails, it must somehow report the error. With pointers, error reporting is easy: the dynamic_cast expression returns a NULL pointer so you can test the returned pointer locally. However, references are a serious problem. If the first dynamic_cast expression fails, it will throw a std::bad_cast exception. That means that reference dynamic_casts must be executed inside a try-block, and in addition, you must also include a matching catch(std::bad_cast&) handler to catch such an exception. An optimizing compiler can minimize much of the overhead incurred by exceptions, but your source files will still need to include the inevitable try and catch blocks:

  derived = dynamic_cast<derived&> (baseobj);
catch(std::bad_cast& e)
//..deal with the exception

Compare this with the following pointer version:

if (derived *p= dynamic_cast<derived*> (&baseobj))
//...use p safely

Which one is simpler and more efficient? I choose the latter.