# Polymorphism

Polymorphism is an opportunity for different classes of objects, related through inheritance, to respond in various ways when calling the same function element. It helps to create a universal mechanism describing the behavior of not only the base class, but also descendant classes.

Let's continue to develop a base class CShape, and define a member function GetArea(), designed to calculate the area of a shape. In all the descendant classes, produced by inheritance from the base class, we redefine this function in accordance with rules of calculating the area of a particular shape.

For a square (class CSquare), the area is calculated through its sides, for a circle (class CCircle), area is expressed through its radius etc. We can create an array to store objects of CShape type, in which both objects of a base class and those of all descendant classes can be stored. Further we can call the same function for each element of the array.

Example:

 //--- Base class class CShape   { protected:     int            m_type;                // Shape type    int            m_xpos;                // X - coordinate of the base point    int            m_ypos;                // Y - coordinate of the base point public:    void           CShape(){m_type=0;};   // constructor, type=0    int            GetType(){return(m_type);};// returns type of the shape virtual    double         GetArea(){return (0); }// returns area of the shape   };

Now, all of the derived classes have a member function getArea(), which returns a zero value. The implementation of this function in each descendant will vary.

 //--- The derived class Circle class CCircle : public CShape            // After a colon we define the base class   {                                      // from which inheritance is made private:    double         m_radius;              // circle radius   public:    void           CCircle(){m_type=1;};  // constructor, type=1     void           SetRadius(double r){m_radius=r;};    virtual double GetArea(){return (3.14*m_radius*m_radius);}// circle area   };

For the class Square the declaration is the same:

 //--- The derived class Square class CSquare : public CShape            // After a colon we define the base class   {                                      // from which inheritance is made private:    double          m_square_side;        // square side   public:    void            CSquare(){m_type=2;}; // constructor, type=1    void            SetSide(double s){m_square_side=s;};    virtual double  GetArea(){return (m_square_side*m_square_side);}// square area   };

For calculating the area of the square and circle, we need the corresponding values of m_radius and m_square_side, so we have added the functions SetRadius() and SetSide() in the declaration of the corresponding class.

It is assumed that object of different types (CCircle and CSquare) derived from one base type CShape are used in our program. Polymorphism allows creating an array of objects of the base CShape class, but when declaring this array, these objects are yet unknown and their type is undefined.

The decision on what type of object will be contained in each element of the array will be taken directly during program execution. This involves the dynamic creation of objects of the appropriate classes, and hence the necessity to use object pointers instead of objects.

The new operator is used for dynamic creation of objects. Each such object must be individually and explicitly deleted using the delete operator. Therefore we will declare an array of pointers of CShape type, and create an object of a proper type for each element (new Class_Name), as shown in the following script example:

 //+------------------------------------------------------------------+ //| Script program start function                                    | //+------------------------------------------------------------------+ void OnStart()   { //--- Declare an array of object pointers of the base type     CShape *shapes;   // An array of pointers to CShape object   //--- Here fill in the array with derived objects //--- Declare a pointer to the object of CCircle type    CCircle *circle=new CCircle(); //--- Set object properties at the circle pointer    circle.SetRadius(2.5); //--- Place the pointer value in shapes    shapes=circle;   //--- Create another CCircle object and write down its pointer in shapes    circle=new CCircle();    shapes=circle;    circle.SetRadius(5);   //--- Here we intentionally "forget" to set a value for shapes //circle=new CCircle(); //circle.SetRadius(10); //shapes=circle;   //--- Set NULL for the element that is not used    shapes=NULL;   //--- Create a CSquare object and write down its pointer to shapes    CSquare *square=new CSquare();    square.SetSide(5);    shapes=square;   //--- Create a CSquare object and write down its pointer to shapes    square=new CSquare();    square.SetSide(10);    shapes=square;   //--- We have an array of pointers, get its size    int total=ArraySize(shapes); //--- Pass in a loop through all pointers in the array     for(int i=0; i<5;i++)      {       //--- If the pointer at the specified index is valid       if(CheckPointer(shapes[i])!=POINTER_INVALID)         {          //--- Log the type and square of the shape          PrintFormat("The object of type %d has the square %G",                shapes[i].GetType(),                shapes[i].GetArea());         }       //--- If the pointer has type POINTER_INVALID       else         {          //--- Notify of an error          PrintFormat("Object shapes[%d] has not been initialized! Its pointer is %s",                      i,EnumToString(CheckPointer(shapes[i])));         }      }   //--- We must delete all created dynamic objects    for(int i=0;i

Please note that when deleting an object using the delete operator, the type of its pointer must be checked. Only objects with the POINTER_DYNAMIC pointer can be deleted using delete. For pointers of other type, an error will be returned.

But besides the redefining of functions during inheritance, polymorphism also includes the implementation of one and the same functions with different sets of parameters within a class. This means that the class may have several functions with the same name but with a different type and/or set of parameters. In this case, polymorphism is implemented through the function overload.