Everyone has played nethack, so everyone knows that polymorphism is Greek for "many shapes." In C++ it means supporting different methods for related objects, and allowing runtime binding to the appropriate one. The mechanism by which this is supported in C++ is overloading—all the polymorphic methods are given the same name, and the runtime system figures out which one is the appropriate one. This is needed when you inherit: sometimes it's not possible to tell at compile time whether you have an object of the base class or the inheriting class. The process of figuring this out and calling the right method is called "late binding," and you tell the compiler you want it by applying the virtual keyword to a method. With ordinary compile-time overloading the signature of the functions must differ enough so that the
compiler can tell by looking at the argument types which function is intended. With virtual functions the signatures must be identical and the polymorphism is resolved at run time. Polymorphism is the last highlight of C++ that we will cover, and it is easier to explain with a code example than with text.
Let's start by considering our familiar base class of Fruit and adding a method to peel a fruit object.
Once again, we won't fill in the details of peeling, just have it print a message.
#include <stdio.h>
class Fruit { public: void peel(){printf("peeling a base class
fruit\n");}
slice();
juice();
private: int weight, calories_per_oz;
} ;
When we declare a fruit object, and invoke the peel() method like this,
Fruit banana;
banana.peel();
we will get the message
"peeling a base class fruit"
So far, so good. Now consider deriving our apple class, and giving this its own method for peeling!After all, apples are peeled somewhat differently than bananas: you can peel a banana with your thumbs, but you need a knife to peel an apple. We know we can have methods with the same name, as
C++ can cope with overloading.
class Apple : public Fruit {
public:
void peel() {printf("peeling an apple\n");}
void make_candy_apple(float weight);
};
Let's declare a pointer to a fruit, then make it point to an apple object (which inherits from the fruit
class), and see what happens when we try peeling.
Fruit * p;
p = new Apple;
p->peel();
If you try it, you'll get output like this:
% CC fruits.cpp
% a.out
peeling a base class fruit In other words, the Apple-specific method peel() wasn't called, the base class's peel() was! :)
0 comments:
Post a Comment