Полиморфизм в 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.