FAQ Lite
Herança - Classes-base Abstratas (ABCs)

[ 22.1 ] Qual o grande benefício da separação entre interface e implementação?
[ 22.2 ] Como eu separo a interface da implementação em C++ (como Modula-2)?
[ 22.3 ] O que é uma ABC?
[ 22.4 ] O que é uma função membro virtual pura?
[ 22.5 ] Como você define um construtor de cópia ou um operator de atribuição para uma classe que contém um pointer para uma classe base abstrata?

[ 22.1 ] Qual o grande benefício da separação entre interface e implementação?

No âmbito de desenvolvimento de software, as interfaces são os recursos mais valiosos da empresa. Projetar uma interface leva mais tempo do que implementá-la em uma classe concreta, que realiza as funções da interface.. Mais ainda, o projeto da interface geralmente consome tempo de profissionais mais experientes e mais caros.

Posto que interfaces são recursos valiosos, devem ser protegidas e não embaralhadas com as estruturas de dados ou com outros artefatos de implementação. Por isso você deve separar a interface da implementação.

Topo
[ 22.2 ] Como eu separo a interface da implementação em C++ (como Modula-2)?

Use uma ABC (Abstract Base Class) Classe Base Abstrata
Topo
[ 22.3 ] O que é uma ABC?

Uma classe base abstrata (Abstract Base Class).

Em nível de projeto, uma classe base abstrata (ABC) corresponde a um conceito abstrato. Se você pergunta a um mecânico se ele concerta veículos, ele provavelmente vai ter que imaginar que tipo-de veículo você tem em mente. É provável que ele não concerte ônibus espaciais, barcos de regata, bicicletas nem submarinos nucleares. O problema é que veículo é um conceito abstrato (por exemplo, você não pode construir um veículo, a menos que você saiba que tipo-de veículo construir). Em C++, class Vehicle deve ser uma ABC, tendo Bicycle, SpaceShutlle, etc. como subclasses (um OceanLiner é um tipo-de Vehicle). No mundo real de OO, ABCs representam conceitos abstratos de modo completo.

Em nível de programação, uma ABC é uma classe que tem uma ou mais funções membro virtual pura. Você não pode fazer um objeto (instância) de uma ABC

Topo
[ 22.4 ] O que é uma função membro virtual pura?

Uma declaração de função membro que transforma uma classe normal em uma classe abstrata (ou seja, uma ABC). Normalmente você implementa essa função apenas na classe derivada.

Algumas funções membro existem apenas conceitualmente, não tendo uma definição razoável, inteligível, palpável. Por exemplo, suponha que eu lhe peça para desenhar uma Forma na localização (x,y) com tamanho 7. Você vai me perguntar -Que tipo de forma eu deve desenhar? (círculos, quadrados, hexágonos, etc. são desenhados diferentemente).

Em C++, nós precisamos indicar a existência da função membro draw() - para que os usuários da classe possam invocá-la quando tenham um Shape* ou um Shape& - mas reconhecemos que essa função possa ser definida apenas nas subclasses:

    class Shape {
    public:
      virtual void draw() const = 0;  // = 0 means it is "pure virtual"
      // ...
    }; 
Essa função virtual pura transforma Shape em uma ABC (Classe Base Abstrata). Se você preferir, pode pensar na sintáx = 0; como se fosse um caso em que o código estivesse em um pointer NULL. Com essa construção, Shape promete um serviço aos seus usuários, embora Shape ainda não contenha qualquer código para cumprir essa promessa. Isso força qualquer objeto real, que venha a ser criado a partir de uma classe derivada (concreta) de Shape, a ter a função membro indicada, embora a classe base não tenha ainda informação suficiente para definir tal função.

Perceba que de fato é possível estabelecer a definição de uma função virtual pura, mas isso normalmente confunde iniciantes em OO/C++, portanto vamos evitar definições por enquanto.

Topo
[ 22.5 ] Como você define um construtor de cópia ou um operator de atribuição para uma classe que contém um pointer para uma classe base (abstrata)?

Se a classe possui o objeto apontado pelo pointer da classe base (abstrata), use o artifício de construtores virtuais na classe base (abstrata). Tão usual quanto esse artifício, é declarar um método virtual puro clone() na classe base.
    class Shape {
    public:
      // ...
      virtual Shape* clone() const = 0;   // The Virtual (Copy) Constructor
      // ...
    }; 
A partir daí, nós implementamos esse método clone() em cada classe derivada.
    class Circle {
    public:
      // ...
      virtual Shape* clone() const { return new Circle(*this); }
      // ...
    };
    
    class Square {
    public:
      // ...
      virtual Shape* clone() const { return new Square(*this); }
      // ...
    }; 
Agora suponha que cada objeto Fred tenha-um objeto Shape. Naturalmente o objeto Fred não sabe se Shape é um Circle, um Square, ou ... Tanto o construtor de cópia de Fred quanto o operator de atribuição vão invocar o método clone() de Shape para copiar o objeto.
    class Fred {
    public:
      Fred(Shape* p) : p_(p) { assert(p != NULL); }   // p must not be NULL
     ~Fred() { delete p_; }
      Fred(const Fred& f) : p_(f.p_->clone()) { }
      Fred& operator= (const Fred& f)
        {
          if (this != &f) {              // Check for self-assignment
            Shape* p2 = f.p_->clone();   // Create the new one FIRST...
            delete p_;                   // ...THEN delete the old one
            p_ = p2;
          }
          return *this;
        }
      // ...
    private:
      Shape* p_;
    }; 
Topo Anterior Próximo Índice
C++ FAQ Lite
Copyright © 1991-98 by Marshall Cline Ph.D., cline@parashift.com
Tradução: Dagoberto Haele Arnaut

| Home | Bookmarks | Universidades | Para Saber mais | Universidades | WEB Directory | Mapa do site |