Clases abstractas (C++)

Las clases abstractas actúan como expresiones de conceptos generales de los que pueden derivarse clases más concretas. No se puede crear un objeto de un tipo de clase abstracta, pero se pueden usar punteros y referencias a tipos de clase abstracta.

Para crear una clase abstracta, declare al menos una función miembro virtual pura. Se trata de una función virtual declarada mediante la sintaxis del especificador puro (= 0). Las clases derivadas de la clase abstracta deben implementar la función virtual pura o deben ser también clases abstractas.

Considere el ejemplo que se presenta en Funciones virtuales. El propósito de la clase Account es proporcionar funcionalidad general, pero los objetos de tipo Account son demasiado generales para resultar útiles. Eso significa que Account es un buen candidato para una clase abstracta:

// deriv_AbstractClasses.cpp
// compile with: /LD
class Account {
public:
   Account( double d );   // Constructor.
   virtual double GetBalance();   // Obtain balance.
   virtual void PrintBalance() = 0;   // Pure virtual function.
private:
    double _balance;
};

La única diferencia entre esta declaración y la anterior consiste en que PrintBalance se declara con el especificador puro (= 0).

Restricciones para el uso de clases abstractas

No se pueden usar clases abstractas para:

  • Variables o datos de miembro

  • Tipos de argumento

  • Tipos de valor devuelto de función

  • Tipos de conversiones explícitas

Si el constructor para una clase abstracta llama a una función virtual pura, ya sea directa o indirectamente, el resultado es indefinido. Sin embargo, los constructores y destructores para las clases abstractas pueden llamar a otras funciones miembro.

Funciones virtuales puras definidas

En las clases abstractas, las funciones virtuales puras pueden estar definidas o tener una implementación. Solo se puede llamar a estas funciones mediante la sintaxis completa:

abstract-class-name::function-name()

Las funciones virtuales puras definidas son útiles al diseñar jerarquías de clases cuyas clases base incluyen destructores virtuales puros. Esto se debe a que siempre se llama a los destructores de clase base durante la destrucción de objetos. Considere el ejemplo siguiente:

// deriv_RestrictionsOnUsingAbstractClasses.cpp
// Declare an abstract base class with a pure virtual destructor.
// It's the simplest possible abstract class.
class base
{
public:
    base() {}
    // To define the virtual destructor outside the class:
    virtual ~base() = 0;
    // Microsoft-specific extension to define it inline:
//  virtual ~base() = 0 {};
};

base::~base() {} // required if not using Microsoft extension

class derived : public base
{
public:
    derived() {}
    ~derived() {}
};

int main()
{
    derived aDerived; // destructor called when it goes out of scope
}

En el ejemplo se muestra la forma en que una extensión del compilador de Microsoft permite agregar una definición insertada a un objeto ~base() virtual puro. También se puede definir fuera de la clase mediante base::~base() {}.

Cuando el objeto aDerived sale del ámbito, se llama al destructor de la clase derived. El compilador genera código para llamar implícitamente al destructor para la clase base después del destructor derived. La implementación vacía para el objeto ~base de la función virtual pura garantiza que al menos existe alguna implementación para la función. Sin él, el enlazador genera un error de símbolo externo sin resolver para la llamada implícita.

Nota:

En el ejemplo anterior, la función virtual pura base::~base se llama implícitamente desde derived::~derived. También es posible llamar a funciones virtuales puras explícitamente mediante el nombre completo de la función miembro. Estas funciones deben tener una implementación; de lo contrario, la llamada produce un error en tiempo de vínculo.

Consulte también

Herencia