OOPortal OOPortal


Inheritance/Polymorphism  «Prev  Next»
Lesson 14 The dynamic_cast operator
Objective Four different situations, choose most appropriate form

C++ dynamic_cast Operator

The dynamic_cast operator has the form:
dynamic_cast< type >( v )

where type must be a pointer or reference to a class type and v must be a corresponding pointer value or reference value. This cast is used with classes having virtual functions. For example:

class Base { virtual void foo(); ..... };
class Derived : Base { ..... };

void fcn(Derived* ptr){
  Base* bptr = dynamic_cast<Base*>(ptr);
}       

In this example, the cast converts the pointer value ptr to a Base*. If the conversion is inappropriate, a value of 0 is returned. Dynamic casts also work with reference types. Conceptually, the derived type object has a subobject that corresponds to the base type. The conversion replaces the derived type pointer value or reference with an appropriate base type pointer value or reference.


Obtaining Run-Time Type Information

When you have a pointer or reference that can refer to an object of multiple classes in a hierarchy, you occasionally need to obtain the actual type of an object. There are two common ways that this is done. A dynamic cast verifies that the pointer or reference can be safely converted to a pointer or reference of a derived class. The typeid operator yields the exact type of an object. We describe both features in the following sections.

Dynamic Casts

The dynamic_cast operator requires a type as a template parameter, followed by a parameter that must be a pointer or reference
// Implicitly converts from Manager to Employee
Employee* e = new Manager("Sarah Smith", 67000, 2000);
// Explicitly converts from Employee to Manager
Manager* m = dynamic_cast<Manager*>(e);

The dynamic cast succeeds if the template type matches the actual type of the pointer or reference. In that case, the dynamic_cast operator returns the pointer or reference, converted to the template type. If the type is not correct, a NULL pointer is returned. Comparing the result to NULL is therefore equivalent to testing the type of the parameter.
for (int i = 0; i < department.size(); i++){
 Manager* m = dynamic_cast<Manager*>(department[i]);
 if (m != NULL){
  cout << "Employee " << department[i]->get_name()
  << " is a manager.\n";
  m->set_bonus(2000); // Can now invoke manager member functions
 } 
 else
  cout << "Employee " << department[i]->get_name() << " is not a manager.\n";
 }

The assignment of a Manager value to an Employee variable is sometimes termed an upcast, because you are moving “up” the class hierarchy. Similarly, the use of the dynamic cast, which does just the reverse, is termed a downcast, because you are moving down the class hierarchy as it is written on the page. If the dynamic_cast operation is used with a reference, instead of a pointer, a failure results in a bad_cast exception being thrown, rather than a NULL pointer, because there is no equivalent to a NULL pointer when using references. To use a dynamic cast, objects must belong to a class with at least one virtual function.
A static_cast is similar, but performs no run-time check on the result. If the programmer has made a mistake and the change in type is not valid, no indication will be given. This makes static casts much more dangerous than dynamic casts. A static cast should only be used for primitive types (for example, converting an integer into a double) or non-polymorphic types.
int max = 42;
double dmax = static_cast < double> (max); // One way to convert to double

Dynamic Cast Syntax

dynamic_cast <type_name>(expression)

Example:
Manager* m = dynamic_cast<Manager*>(department[i]);

Purpose: Safely test the type of a polymorphic variable, converting to derived class type if appropriate, returning a NULL pointer if not.

Cast Operator - Exercise

Click the Exercise link below to choose the most appropriate form of cast operator in four different situation.
Cast Operator - Exercise