Pergunta

O que as pessoas aqui usar construtores C ++ Abstract classe base para no campo? Estou a falar de classes de interface puro com nenhum membro de dados e há membros virtuais não-puros.

Alguém pode demonstrar quaisquer expressões que usam construtores ABC de forma útil? Ou é apenas intrínseco à natureza do uso de ABC para implementar interfaces que eles permanecem vazios, inline e protegido?

Foi útil?

Solução

Alguém pode demonstrar quaisquer expressões que usam construtores ABC de forma útil?

Aqui está um exemplo, embora seja um artificial, exemplo incomum.

Você pode usá-lo para manter uma lista de todas as instâncias:

class IFoo
{
private:
  //static members to keep a list of all constructed instances
  typedef std::set<IFoo*> Set;
  static Set s_set;

protected:
  //new instance being created
  IFoo()
  {
    s_set.insert(this);
  }

public:
  //instance being destroyed
  virtual ~IFoo()
  {
    s_set.remove(this);
  }

  ... plus some other static method and/or property
      which accesses the set of all instances ...
};

Ou é apenas intrínseco à natureza do uso de ABC para implementar interfaces que eles permanecem vazios, inline e protegido?

Mais geralmente eles estão apenas não declarados em tudo! Não há nenhuma razão para declará-los:

  • Vazio e em linha => por que se preocupar declará-la?
  • Protegido => o ABC provavelmente já tem alguns puros virtuais métodos e, portanto, já não pode ser instanciado, exceto como uma subclasse.

Outras dicas

Suponha que haja algum comportamento que é comum para todas as classes derivadas. Tais como registrar-se em algum registro externo, ou verificar a validade de algo.

Tudo isso código comum pode ser colocado no construtor de classe base, e ele será chamado implicitamente dos construtores de cada uma das classes derivadas.

Como pode construtor de uma classe base abstrata ser usado para qualquer coisa?

Suponha que você tenha uma classe abstrata base B e uma classe derivada D. Quando um objeto do tipo D é criado, o construtor de B é chamado pela primeira vez, mas nesse ponto, o objeto "é" ainda do tipo B (ver aqui ) - em particular, de chamar qualquer funções virtuais de o corpo do construtor do B vai chamar próprias implementações do B dessas funções. Mas, se B é uma classe abstrata pura, nenhuma dessas funções virtuais são definidos, de modo que o programa irá falhar imediatamente.

Eu estou supondo que você destina para o construtor de B para ligar para (por exemplo D's) implementação de uma função virtual da classe mais derivado, certo? Isso seria uma má idéia em geral, porque objeto D's ainda não está totalmente construído, portanto, quaisquer acessos a variáveis ??de membro em D de dentro implementação da função virtual D's iria acessar a memória uninitialised.

Lembre-se:. "aquisição de recurso é inicialização"

Às vezes, usamos classes base abstratas como uma espécie de mecanismo de bloqueio. Por exemplo, em um ambiente multi-threaded, onde vários tópicos precisam compartilhar um único recurso, em seguida, um thread pode usar o construtor como uma forma de adquirir o recurso, e o destruidor para liberar o recurso

void PlayWithPaintBallGun(Target &target)
{
    PaintBallGun paintBallGun;    // constructor waits until the gun is free,
                                  // then picks it up.

    paintBallGun.Aim(target);     // Shoot something
    paintBallGun.Fire();          //

                                  // Clever! The destructor is automatically
                                  // called when it goes out of scope. So we
                                  // can't forget to put the gun down.
}

Hugo

Eu não consigo pensar em muitos exemplos úteis. Uma classe sem data-membros não tem estado e, portanto, não pode inicializar nada. Você pode ter o construtor / destruidor fazer login para você, no entanto. Por exemplo, para registrar a criação / destruição de toda Visitor objetos:

class Visitor {
public:
    Visitor() {
        std::cout << "Visitor@" << this << " created" 
                  << std::endl;
    }

    virtual ~Visitor() {
        std::cout << "Visitor@" << this << " destroyed" 
                  << std::endl;
    }

    virtual void visitA(A*) = 0;
    virtual void visitB(B*) = 0;
    // ...
};

geralmente o seu apenas para inicializar os membros de valores sensíveis.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top