< Previous | Contents | Next >
An object of a derived class is also a member of the base class. For example, in the Polymorphic Bad Guy program, a Boss object is an Enemy object, too. That makes sense because a boss is really only a specialized kind of enemy. It also makes sense because a Boss object has all of the members of an Enemy object. Okay, so what? Well, because an object of a derived class is also a member of the base class, you can use a pointer to the base class to point to an object of the derived class. That’s what I do in main() with the following line, which instantiates a Boss object on the heap and creates a pointer to Enemy, pBadGuy, that points to the Boss object.
Enemy* pBadGuy = new Boss();
Why in the world would you want to do this? It’s useful because it allows you to deal with objects without requiring that you know their exact type. For example, you could have a function that accepts a pointer to Enemy that could work with either an Enemy or a Boss object. The function wouldn’t have to know the exact type of object being passed to it; it could work with the object to produce different results depending on the object’s type, as long as derived member functions were declared virtual. Because Attack() is virtual, the correct version of the member function will be called (based on the type of object) and will not be fixed by the type of pointer.
I prove that the behavior will be polymorphic in main(). Remember that pBadGuy is a pointer to Enemy that points to a Boss object. So, the following line calls the Attack() member function of a Boss object through a pointer to Enemy, which correctly results in the Attack() member function defined in Boss being
called and the text A boss attacks and inflicts 30 damage points. being displayed on the screen.
pBadGuy->Attack();
Hin t
Virtual functions produce polymorphic behavior through references as well as through pointers.
Tra p
If you override a non-virtual member function in a derived class and call that member function on a derived class object through a pointer to a base class, you’ll get the results of the base class member function and not the derived class member function definition. This is easier to understand with an example. If in the Polymorphic Bad Guy program I hadn’t declared Attack() as virtual, then when I invoked the member function through a pointer to Enemy on a Boss object with pBadGuy->Attack();, I would have gotten the message An enemy attacks and inflicts 10 damage points. This would have happened as a result of early binding, in which the exact member function is bound based on the pointer type—in this case, Enemy. But because Attack() is declared as virtual, the member function call is based on the type of object being pointed to at run time, Boss in this case, not fixed by pointer type. I achieve this polymorphic behavior as the result of late binding because Attack() is virtual. The moral of the story is that you should only override virtual member functions.
Tra p
The benefits of virtual functions aren’t free; there is a performance cost associated with the overhead. Therefore, you should use virtual functions only when you need them.