/*
Virtual Member

A member of a class that can be redefined in its derived classes is known as a virtual member. In order to declare
a member of a class as virtual, we must precede its declaration with the keyword virtual.
*/

#include <iostream>
using namespace std;

class CPolygon {
      protected:
             int width, height;
      public:
             void set_values (int a, int b)
             { 
                  width=a; 
                  height=b; 
             }
      virtual int area ()
      { 
              return (0); 
      }
};

class CRectangle: public CPolygon {
      public:
             int area ()
             { 
                 return (width * height); 
             }
};

class CTriangle: public CPolygon {
      public:
             int area ()
             { 
                 return (width * height / 2); 
             }
};

int main () {
    CRectangle rect;
    CTriangle trgl;
    CPolygon poly;
    CPolygon * ppoly1 = &rect;
    CPolygon * ppoly2 = &trgl;
    CPolygon * ppoly3 = &poly;
    
    ppoly1->set_values (4,5);
    ppoly2->set_values (4,5);
    ppoly3->set_values (4,5);
    
    cout << ppoly1->area() << endl;
    cout << ppoly2->area() << endl;
    cout << ppoly3->area() << endl;
    
    std::cin.get();
    return (0);       
}

/*
Now the three classes (CPolygon, CRectangle and CTriangle) have all the same members: width, height,
set_values() and area().

The member function area() has been declared as virtual in the base class because it is later redefined in each
derived class. You can verify if you want that if you remove this virtual keyword from the declaration of area()
within CPolygon, and then you run the program the result will be 0 for the three polygons instead of 20, 10 and 0.
That is because instead of calling the corresponding area() function for each object (CRectangle::area(),
CTriangle::area() and CPolygon::area(), respectively), CPolygon::area() will be called in all cases since the
calls are via a pointer whose type is CPolygon*.

Therefore, what the virtual keyword does is to allow a member of a derived class with the same name as one in
the base class to be appropriately called from a pointer, and more precisely when the type of the pointer is a
pointer to the base class but is pointing to an object of the derived class, as in the above example.

A class that declares or inherits a virtual function is called a polymorphic class.

Note that despite of its virtuality, we have also been able to declare an object of type CPolygon and to call its own
area() function, which always returns 0.
*/
