Interfaces em C ++ (classes abstratas)

Uma interface descreve o comportamento ou os recursos de uma classe C ++ sem se comprometer com uma implementação específica dessa classe.

As interfaces C ++ são implementadas usando abstract classes e essas classes abstratas não devem ser confundidas com abstração de dados, que é um conceito de manter os detalhes de implementação separados dos dados associados.

Uma classe se torna abstrata, declarando pelo menos uma de suas funções como pure virtualfunção. Uma função virtual pura é especificada colocando "= 0" em sua declaração da seguinte forma -

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
};

O propósito de um abstract class(freqüentemente referido como ABC) é fornecer uma classe base apropriada da qual outras classes podem herdar. Classes abstratas não podem ser usadas para instanciar objetos e servem apenas como uminterface. A tentativa de instanciar um objeto de uma classe abstrata causa um erro de compilação.

Assim, se uma subclasse de um ABC precisa ser instanciada, ela deve implementar cada uma das funções virtuais, o que significa que suporta a interface declarada pelo ABC. A falha em substituir uma função virtual pura em uma classe derivada e, em seguida, tentar instanciar objetos dessa classe é um erro de compilação.

As classes que podem ser usadas para instanciar objetos são chamadas concrete classes.

Exemplo de classe abstrata

Considere o exemplo a seguir, onde a classe pai fornece uma interface para a classe base para implementar uma função chamada 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;
}

Quando o código acima é compilado e executado, ele produz o seguinte resultado -

Total Rectangle area: 35
Total Triangle area: 17

Você pode ver como uma classe abstrata definiu uma interface em termos de getArea () e duas outras classes implementaram a mesma função, mas com algoritmos diferentes para calcular a área específica da forma.

Estratégia de Projeto

Um sistema orientado a objetos pode usar uma classe base abstrata para fornecer uma interface comum e padronizada apropriada para todos os aplicativos externos. Então, por meio da herança dessa classe base abstrata, classes derivadas são formadas que operam de forma semelhante.

Os recursos (ou seja, as funções públicas) oferecidos pelos aplicativos externos são fornecidos como funções virtuais puras na classe base abstrata. As implementações dessas funções virtuais puras são fornecidas nas classes derivadas que correspondem aos tipos específicos do aplicativo.

Essa arquitetura também permite que novos aplicativos sejam adicionados a um sistema facilmente, mesmo após o sistema ter sido definido.