Unetway

C ++ - Интерфейсы (абстрактные классы)

Интерфейс описывает поведение или возможности класса C ++, не связываясь с конкретной реализацией этого класса.

Интерфейсы C ++ реализуются с использованием абстрактных классов,и эти абстрактные классы не следует путать с абстракцией данных, которая представляет собой концепцию сохранения деталей реализации отдельно от связанных данных.

Класс делается абстрактным, объявляя хотя бы одну из своих функций чистой виртуальной функцией. Чистая виртуальная функция задается путем размещения в объявлении «= 0» следующим образом:

class Box {
   public:
      // pure virtual function
      virtual double getVolume() = 0;
      
   private:
      double length;      // Length of a box
      double breadth;     // Breadth of a box
      double height;      // Height of a box
};

Цель абстрактного класса (часто называемого ABC) заключается в предоставлении соответствующего базового класса, из которого могут наследовать другие классы. Абстрактные классы не могут использоваться для создания объектов и служат только как интерфейс . Попытка создать экземпляр объекта абстрактного класса вызывает ошибку компиляции.

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

Классы, которые могут использоваться для создания объектов, называются конкретными классами .

Пример абстрактного класса

Рассмотрим следующий пример, когда родительский класс предоставляет интерфейс базовому классу для реализации функции getArea () -

#include <iostream>
 
using namespace std;
 
// Base class
class Shape {
   public:
      // pure virtual function providing interface framework.
      virtual int getArea() = 0;
      void setWidth(int w) {
         width = w;
      }
   
      void setHeight(int h) {
         height = h;
      }
   
   protected:
      int width;
      int height;
};
 
// Derived classes
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);
   
   // Print the area of the object.
   cout << "Total Rectangle area: " << Rect.getArea() << endl;

   Tri.setWidth(5);
   Tri.setHeight(7);
   
   // Print the area of the object.
   cout << "Total Triangle area: " << Tri.getArea() << endl; 

   return 0;
}

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

Total Rectangle area: 35
Total Triangle area: 17

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

Стратегия проектирования

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

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

Эта архитектура также позволяет легко добавлять новые приложения в систему даже после того, как система была определена.