Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Язык C

Полиморфизм в 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);
    }
};
int main() {
    Shape *shape;
    Rectangle rec(10,7);
    Triangle tri(10,5);
    // адрес Rectangle
    shape = &rec;
    shape->area();
    // адрес Triangle
    shape = &tri;
    shape->area();
    return 0;
}

Результат компиляции и выполнения:

Parent class area :
Parent class area :

Причина неверного вывода: вызов area() зафиксирован компилятором как версия базового класса — это статическое разрешение (static linkage) или раннее связывание (early binding).

Теперь сделаем небольшое изменение: добавим ключевое слово virtual перед объявлением area() в базовом классе:

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

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

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

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

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

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

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

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

class Shape {
protected:
    int width, height;
public:
    Shape(int a = 0, int b = 0) { width = a; height = b; }
    // чисто виртуальная функция
    virtual int area() = 0;
};

= 0 сообщает компилятору, что у функции нет тела. Такая виртуальная функция называется чисто виртуальной.

Язык C

  1. Освоение операторов C++: полное руководство с практическими примерами
  2. Как передавать массивы в функции в C++: практическое руководство
  3. Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
  4. Дружественные функции и классы в C++: мастерство контроля доступа
  5. Шаблоны классов в C++: практическое руководство
  6. Перегрузка операторов в C++: практическое руководство с примерами кода
  7. Классы хранения в C++: область видимости, время жизни и использование
  8. Перегрузка в C++: функции и операторы — подробное руководство
  9. Абстракция данных в C++: разделение интерфейса и реализации
  10. Инкапсуляция данных в C++: защита вашего кода