Интерфейсы в C++: абстрактные классы и чисто виртуальные функции
Интерфейс описывает поведение или возможности класса C++ без привязки к конкретной реализации.
Интерфейсы в C++ реализуются через абстрактные классы, их не следует путать с абстракцией данных — концепцией разделения деталей реализации от связанных данных.
Класс становится абстрактным, если хотя бы одна из его функций объявлена как чисто виртуальная. Чисто виртуальная функция задаётся добавлением = 0 в объявлении:
class Box {
public:
// чисто виртуальная функция
virtual double getVolume() = 0;
private:
double length;
double breadth;
double height;
};
Цель абстрактного класса (часто называемого ABC) — предоставить подходящий базовый класс для наследования другими классами. Абстрактные классы нельзя использовать для создания объектов, они служат только интерфейсом. Попытка создать объект абстрактного класса вызовет ошибку компиляции.
Таким образом, если подкласс ABC должен быть инстанциирован, он должен реализовать каждую виртуальную функцию, то есть поддерживать интерфейс, объявленный ABC. Неудача при переопределении чисто виртуальной функции в производном классе при попытке создать его объекты также вызовет ошибку компиляции.
Классы, объекты которых можно создавать, называются конкретными классами.
Пример абстрактного класса
Пример, где базовый класс предоставляет интерфейс для реализации функции getArea():
Live Demo#include <iostream>
using namespace std;
// Базовый класс
class Shape {
public:
// чисто виртуальная функция, предоставляющая интерфейс
virtual int getArea() = 0;
void setWidth(int w) { width = w; }
void setHeight(int h) { height = h; }
protected:
int width;
int height;
};
// Производные классы
class Rectangle: public Shape {
public:
int getArea() { return (width * height); }
};
class Triangle: public Shape {
public:
int getArea() { return (width * height) / 2; }
};
int main(void) {
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
cout << "Total Rectangle area: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
cout << "Total Triangle area: " << Tri.getArea() << endl;
return 0;
}
Результат:
Total Rectangle area: 35 Total Triangle area: 17
Видно, как абстрактный класс задал интерфейс через getArea(), а два других класса реализовали его по-разному — с алгоритмами, специфичными для фигуры.
Стратегия проектирования
Объектно-ориентированная система может использовать абстрактный базовый класс для предоставления общего стандартизированного интерфейса для всех внешних приложений. Через наследование от этого абстрактного базового класса формируются производные классы, работающие схожим образом.
Возможности (публичные функции), предоставляемые внешними приложениями, оформляются как чисто виртуальные функции в абстрактном базовом классе. Их реализации даются в производных классах, соответствующих конкретным типам приложений.
Такая архитектура позволяет легко добавлять новые приложения в систему даже после её определения.
Язык C
- Абстрактные классы и методы в C#: практическое руководство
- Освоение операторов C++: полное руководство с практическими примерами
- Классы и объекты в C++: практическое руководство по объектно-ориентированному программированию
- Дружественные функции и классы в C++: мастерство контроля доступа
- Шаблоны классов в C++: практическое руководство
- Абстрактные классы и методы в Java: полное руководство
- Структуры C++ против классов: практическое руководство для разработчиков встроенных систем
- Абстрактные классы в C#: практическое руководство с примерами кода
- Java: объекты, классы и основные концепции ООП
- Абстракция в Java: упрощение кода и повышение читаемости