Interfaces em C++: Guia para quem está cansado de pesquisar
\n\nSe você já programou em Java ou C# e depois migrou para C++, certamente já se perguntou: "Onde está a palavra-chave interface?". Spoiler: ela não existe. Em C++, as interfaces são implementadas de outra forma — através de classes abstratas. E isso não é um bug, é uma feature que oferece uma flexibilidade incrível.
\n\nNo Stack Overflow, a pergunta "How do you declare an interface in C++?" acumula milhares de visualizações. Isso significa que até desenvolvedores experientes às vezes se confundem. Hoje vamos entender de uma vez por todas como declarar uma interface em C++ para que seu código seja limpo e o compilador fique satisfeito.
\n\nO que é uma interface em C++? (Spoiler: é uma classe abstrata)
\n\nNa POO clássica, uma interface é um contrato. A classe que implementa a interface deve fornecer a implementação de todos os seus métodos. Em C++, esse papel é desempenhado por uma classe abstrata — uma classe que contém pelo menos uma função virtual pura (pure virtual function).
\n\nLembre-se da regra principal:
\n- \n
- Interface = classe onde todos os métodos são virtuais puros. \n
- Classe abstrata = classe onde pelo menos um método é virtual puro (mas pode ter métodos comuns com implementação). \n
Para uma interface pura, usamos exatamente a primeira opção: nenhuma lógica, apenas declarações.
\n\nComo declarar uma interface pura: sintaxe básica
\n\nAqui está um exemplo mínimo de interface para uma figura geométrica:
\n\nclass IShape {\npublic:\n virtual double area() const = 0; // Função virtual pura\n virtual double perimeter() const = 0; // Outra\n virtual ~IShape() {} // Destrutor virtual — obrigatório!\n};\n\nObserve o = 0 no final da declaração. Esta é a marcação mágica "virtual puro". Esse método não tem corpo (implementação) na classe base.
Pontos-chave:
\n- \n
- Prefixo I no nome da classe — uma convenção não oficial para interfaces (I = Interface). Não é obrigatório usar, mas facilita a leitura do código. \n
- Destrutor virtual é obrigatório. Se você excluir um objeto através de um ponteiro para a interface, sem um destrutor virtual o comportamento será indefinido (ou seja, o programa irá falhar). \n
- Todos os métodos public — a interface deve ser acessível para chamadas externas. \n
Implementação da interface: das palavras à ação
\n\nAgora vamos escrever uma classe que implementa nossa interface IShape. Que seja um círculo:
class Circle : public IShape {\nprivate:\n double radius;\npublic:\n explicit Circle(double r) : radius(r) {}\n\n double area() const override {\n return 3.14159 * radius * radius;\n }\n\n double perimeter() const override {\n return 2 * 3.14159 * radius;\n }\n};\n\nA palavra-chave override (C++11 e posteriores) não é obrigatória, mas é altamente recomendada. Ela força o compilador a verificar se você está realmente sobrescrevendo um método virtual da classe base. Errou o nome? O compilador dirá: "Erro! Esse método não existe na interface".
Polimorfismo em ação
\n\nAgora a parte mais interessante — podemos trabalhar com diferentes figuras através de uma interface única:
\n\nvoid printShapeInfo(const IShape& shape) {\n std::cout << "Area: " << shape.area() << "\\n";\n std::cout << "Perimeter: " << shape.perimeter() << "\\n";\n}\n\nint main() {\n Circle c(5.0);\n printShapeInfo(c); // Funciona!\n return 0;\n}\n\nA função printShapeInfo recebe uma referência para IShape. Ela não se importa qual objeto foi passado — círculo, quadrado ou triângulo. Enquanto eles implementarem a interface, tudo funcionará. Isso é polimorfismo
Blogs
Book Recommendations
Leia também