Учебники

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

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

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

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

Live Demo

#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 ().

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

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

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

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

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

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

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