How C++ Does Polymorphism
Adding the keyword virtual to our base class method, and making no other changes results in
#include <stdio.h>
class Fruit {
public: virtual void peel(){printf("peeling a base class
fruit\n");}
slice(); juice();
private: int weight, calories_per_oz;
} ;
And the compilation and execution is
% CC fruits.cpp
% a.out
peeling an apple
Exactly as desired. So far, this could all have been achieved at compile time, but polymorphism is a
runtime effect. It refers to the process of C++ objects deciding at runtime which function should be
called to carry out a particular operation.
The runtime system looks at the object that has called the overloaded method, and chooses the method
that goes with that class of object. If this is a derived object, we don't want it to call the base class
version. We want it to call the derived class version, but this may not have been seen by the compiler
when the base class was compiled. Therefore, this must be done dynamically at runtime, or, in C++
terminology, "virtually."
Single inheritance is usually implemented by having each object contain a pointer vptr to a vector
vtbl of function pointers. There is one of these vectors for each class, and there is one entry in the
vector for each method in the class. In this way, the implementation code is shared by all objects of a
given class. The vector is laid out so that a given function pointer lies at the same offset in the virtual
tables for all subclasses of a class. Each method call can be mapped to a vtbl offset at compiletime.
At runtime, the call is made indirectly through the pointer at the appropriate offset. Multiple
inheritance requires a slightly more complicated scheme with another layer of indirection. If that didn't
make sense, draw yourself a picture of it; it's the end of the line for this particular bus.
Fancy Pants Polymorphism
There are a lot more fancy tricks that you can pull with polymorphism, and sometimes it's downright
essential. It makes a derived class's method preferred over those of the base class, but still allows the
base class ones to be used if no derived ones have been defined. Sometimes a method does not know
at compiletime whether it is operating on an object of its own class or one derived from it.
Polymorphism says this has to work correctly.