Suppose you decided to derive the Weapon class and the Scroll class from a base class GameObject. You've got an inventory of GameObject pointers, each of which points to a Weapon or Scroll, and you picked out one of those pointers. You want to see if it's pointing to a Scroll, and if so, you want to read that scroll. But now the trouble is, you've got a GameObject pointer and you need a Scroll pointer. (Presumably, GameObject does not have a read member function, since read doesn't make sense for GameObjects other than Scrolls.)
Consider this: You have a collection of Landmark pointers, each of which points to a Hotel, a Restaurant, a Library, etc. At the request of a hungry user, you want to visit every pointer in the collection, but display only the Restaurants and their food quality.
class Landmark { … virtual ~Landmark(); // Base classes should have a virtual dtor string name() const; … }; class Restaurant : public Landmark { … int foodQuality(); … }; class Library : public Landmark { … }; … Landmark* lp; … lp = …; // Set lp to point to a Restaurant or a Library object
How do we find out if lp really points to a Restaurant object? With
dynamic_cast
:
Restaurant* rp = dynamic_cast<Restaurant*>(lp); // Try to convert lp if (rp != nullptr) // if result is not null, lp really points to a Restaurant cout << rp->name() << " has quality " << rp->foodQuality() << endl; else // null result means lp pointed to some other kind of landmark cout << lp->name() << " is not a restaurant" << endl;
Note: dynamic_cast
does not copy the object pointed to; if it
doesn't return a null pointer, it simply returns a pointer to the same object,
but with the pointer being of the derived type.
Note: dynamic_cast
only works for classes with at least one
virtual function. A base class should always have a virtual destructor,
so that's an easy requirement to meet.
Stylistic note: Don't overuse dynamic_cast
. In most cases,
when you have a base pointer, and you want to do different things depending
on the kind of derived object it actually points to, just call a virtual
function declared in the base class and implemented differently in the
derived classes.