Unetway

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

Слово полиморфизм означает наличие многих форм. Как правило, полиморфизм возникает, когда существует иерархия классов, и они связаны наследованием.

Полиморфизм 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() устанавливается один раз компилятором как версия, определенная в базовом классе. Это называется статическим разрешением вызова функции или статической привязкой - вызов функции фиксируется перед выполнением программы. Это также иногда называют ранним связыванием, потому что функция 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(). Вот как обычно используется полиморфизм . У вас разные классы с функцией с тем же именем и даже с теми же параметрами, но с разными реализациями.

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

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

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

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

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

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;
};