Polymorphism 453
14
Casting Down ................................................................................................
An alternative to this approach, still within single inheritance, is to keep the Fly()
method within Pegasusand only call it if the pointer is actually pointing to a Pegasus
object. To make this work, you need to be able to ask your pointer what type it is really
pointing to. This is known as Run Time Type Identification (RTTI).
Because RTTI is a newer feature of the C++ specification, not all compilers support it. If
your compiler does not support RTTI, you can mimic it by putting a method that returns
an enumerated type in each of the classes. You can then test that type at runtime and call
Fly()if it returns Pegasus.
Beware of using RTTI in your programs. Needing to use it might be an indi-
cation of poor inheritance hierarchy design. Consider using virtual functions,
templates, or multiple inheritance instead.
CAUTION
In the previous example, you declared both Horseand Pegasusobjects and placed them
in an array of Horseobjects. Everything was placed as a Horse. With RTTI, you would
check each of these Horses to see if it was just a horse or if indeed a Pegasushad actu-
ally been created.
To call Fly(), however, you must cast the pointer, telling it that the object it is pointing
to is a Pegasusobject, not a Horse. This is called casting down because you are casting
the Horseobject down to a more derived type.
C++ now officially, though perhaps reluctantly, supports casting down using the new
dynamic_castoperator. Here’s how it works.
If you have a pointer to a base class such as Horse, and you assign to it a pointer to a
derived class, such as Pegasus, you can use the Horsepointer polymorphically. If you
then need to get at the Pegasusobject, you create a Pegasuspointer and use the
dynamic_castoperator to make the conversion.
At runtime, the base pointer is examined. If the conversion is proper, your new Pegasus
pointer is fine. If the conversion is improper, if you didn’t really have a Pegasusobject
after all, then your new pointer is null. Listing 14.2 illustrates this point.
LISTING14.2 Casting Down
0: // Listing 14.2 Using dynamic_cast.
1: // Using rtti
2: