Pular para conteúdo

Programação Orientada a Objetos em C++

C++ oferece polimorfismo de runtime por herança e funções virtuais, além de polimorfismo por valor e em compilação. Escolha conforme substituição e posse exigidas.

Interface de runtime

class shape {
public:
    virtual ~shape() = default;
    [[nodiscard]] virtual double area() const = 0;
};

class circle final : public shape {
public:
    explicit circle(double radius) : radius_{radius} {
        if (!(radius >= 0.0)) throw std::invalid_argument{"invalid radius"};
    }

    [[nodiscard]] double area() const override {
        return std::numbers::pi * radius_ * radius_;
    }

private:
    double radius_;
};

O destrutor virtual torna segura a exclusão por ponteiro base. override pede verificação do override; final impede derivação adicional.

Substituibilidade

Herança pública normalmente significa “é substituível por”, não apenas “reutiliza código”. O derivado preserva entradas, saídas, invariantes, falhas, complexidade e vida útil do contrato base.

Herança protegida acopla internals. Prefira composição quando só precisar do comportamento.

Slicing de objetos

Passar ou armazenar derivado por valor base copia somente o subobjeto base:

void inspect(shape value); // impossible here because shape is abstract;
                           // a concrete base would slice derived state

Objetos polimórficos normalmente são acessados por referências ou smart pointers proprietários.

Herança múltipla

Pode combinar interfaces puras independentes. Bases de implementação introduzem ambiguidade, construção complexa e diamantes. Herança virtual resolve um problema específico de base compartilhada, mas aumenta complexidade.

Polimorfismo estático

Templates e concepts não exigem base em runtime, favorecem otimização e valores, mas podem aumentar compilação, binário e diagnósticos. Resolvem problemas distintos.

Erros comuns

  • destrutor não virtual em base polimórfica com exclusão proprietária;
  • esquecer override e criar overload;
  • herança apenas para reutilização;
  • cópia por valor base;
  • ponteiros crus proprietários sem responsabilidade clara;
  • esperar despacho derivado durante construção da base.

Exercícios

  1. Refatore herança usada apenas para reutilizar helper.
  2. Explique quando std::variant é preferível a hierarquia virtual aberta.
  3. Declare a posse de std::vector<std::unique_ptr<shape>>.