Полиморфизм в C ++

Слово polymorphismозначает наличие множества форм. Обычно полиморфизм возникает, когда есть иерархия классов, и они связаны наследованием.

Полиморфизм C ++ означает, что вызов функции-члена приведет к выполнению другой функции в зависимости от типа объекта, который вызывает функцию.

Рассмотрим следующий пример, где базовый класс был производным от двух других классов:

#include <iostream> 
using namespace std;
 
class Shape {
   protected:
      int width, height;
      
   public:
      Shape( int a = 0, int b = 0){
         width = a;
         height = b;
      }
      int area() {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};
class Rectangle: public Shape {
   public:
      Rectangle( int a = 0, int b = 0):Shape(a, b) { }
      
      int area () { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};

class Triangle: public Shape {
   public:
      Triangle( int a = 0, int b = 0):Shape(a, b) { }
      
      int area () { 
         cout << "Triangle class area :" <<endl;
         return (width * height / 2); 
      }
};

// Main function for the program
int main() {
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);

   // store the address of Rectangle
   shape = &rec;
   
   // call rectangle area.
   shape->area();

   // store the address of Triangle
   shape = &tri;
   
   // call triangle area.
   shape->area();
   
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат:

Parent class area :
Parent class area :

Причина неверного вывода заключается в том, что вызов функции area () устанавливается компилятором один раз в качестве версии, определенной в базовом классе. Это называетсяstatic resolution вызова функции, или static linkage- вызов функции фиксируется до выполнения программы. Это также иногда называютearly binding потому что функция area () устанавливается во время компиляции программы.

Но теперь давайте внесем небольшие изменения в нашу программу и перед объявлением area () в классе Shape с ключевым словом virtual чтобы это выглядело так -

class Shape {
   protected:
      int width, height;
      
   public:
      Shape( int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      virtual int area() {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

После этой небольшой модификации, когда предыдущий пример кода компилируется и выполняется, он дает следующий результат:

Rectangle class area
Triangle class area

На этот раз компилятор смотрит на содержимое указателя, а не на его тип. Следовательно, поскольку адреса объектов классов tri и rec хранятся в форме *, вызывается соответствующая функция area ().

Как видите, каждый из дочерних классов имеет отдельную реализацию для функции area (). Вот какpolymorphismобычно используется. У вас есть разные классы с функцией с тем же именем и даже с одинаковыми параметрами, но с разными реализациями.

Виртуальная функция

А virtual функция - это функция в базовом классе, объявленная с использованием ключевого слова virtual. Определение в базовом классе виртуальной функции с другой версией в производном классе сигнализирует компилятору, что нам не нужна статическая связь для этой функции.

Что мы действительно хотим, так это выбор функции, которая будет вызываться в любой заданной точке программы, в зависимости от типа объекта, для которого она вызывается. Такая операция называетсяdynamic linkage, или же late binding.

Чистые виртуальные функции

Возможно, вы захотите включить виртуальную функцию в базовый класс, чтобы ее можно было переопределить в производном классе в соответствии с объектами этого класса, но нет значимого определения, которое вы могли бы дать для функции в базовом классе. .

Мы можем изменить виртуальную функцию area () в базовом классе на следующую:

class Shape {
   protected:
      int width, height;

   public:
      Shape(int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      
      // pure virtual function
      virtual int area() = 0;
};

= 0 сообщает компилятору, что функция не имеет тела и будет вызвана виртуальная функция выше. pure virtual function.