
Shapes 3: Inheritance with virtual function
=========================================== 


This directory contains the same code files as are in the Shapes directory.  
The _only_ change to the code is the addition of the word "virtual" to the 
draw() function declaration in the base class, Shape (i.e. in shape.h).

The programs can be built as before.  But now, yea, the draw() for the circle 
object reports that it is indeed a Circle.  This is behaviour is termed 
"polymorphic".  The same message (the draw() function call) is being sent to
objects of different types.  Each receiver object knows its own type, and 
responds in the appropriate, way for that type.  In other words, the same 
message is invoking different behaviour, based on the receiving object's
type.


Example 1:

In the program using main.cpp, the version of draw() is being selected on the 
basis of (smart_ptr) target type, not the type of the pointer itself.  
(This would also be the case if we had chosen to use raw, rather than smart 
pointers.)  The use of the word "virtual" in the declaration of draw() has made
this a virtual function, and this provides (run-time) polymorphism. 

Incidentally, a virtual function declaration in a base class makes all the 
corresponding derived functions virtual.  This applies even if we have several
levels of inheritance, with classes inheriting directly or indirectly from that
base class.


As before, the suggested build lines are:

g++ -std=c++0x main.cpp shape.cpp circle.cpp -o shapes
or
g++ -std=c++11 main.cpp shape.cpp circle,cpp -o shapes


Example 2:

Corresponding build lines are used for the main_1.cpp version.

Here Circle's version of draw() is now called when a Circle object is passed
by reference, or by its address.  (But not by value.)  And this polymorphic 
behavious has been achieved simply by declaring draw() as virtual in the base
class (Shape).  The parameter types used, to achieve this effect are 
base class pointers or references.

This is a powerful technique, particularly for situations where - unlike here -
the exact types being passed are not known at compile time, but only at run 
time.

(When the derived Circle object is passed by value, the parameter is initialised
with the base class (Shape) part only.  In other words, the argument object is 
sliced to only pass its base class part.  Hence pass by value does not support 
polymorphic usage.)

If the corresponding program from Shapes_2 is built and run, it can be seen 
that the output always reports a Shape type; in the first case because of the 
pass by value; and in all cases because the draw() function is not polymorphic.

