Namespaces
Variants

Abstract class

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Define un tipo abstracto que no puede ser instanciado, pero puede ser utilizado como clase base.

Contenidos

Sintaxis

Una función pure virtual es una función virtual cuyo declarador tiene la siguiente sintaxis:

declarador especificador-virtual  (opcional) = 0

Aquí la secuencia = 0 se conoce como pure-specifier , y aparece inmediatamente después del declarator o después del virt-specifier opcional ( override o final ).

pure-specifier no puede aparecer en una definición de función miembro o friend declaración.

struct Base
{
    virtual int g();
    virtual ~Base() {}
};
struct A : Base
{
    // CORRECTO: declara tres funciones miembro virtuales, dos de ellas puras
    virtual int f() = 0, g() override = 0, h();
    // CORRECTO: el destructor también puede ser puro
    ~A() = 0;
    // ERROR: especificador puro en una definición de función
    virtual int b() = 0 {}
};

Una clase abstracta es una clase que define o hereda al menos una función para la cual el final overrider es pure virtual .

Explicación

Las clases abstractas se utilizan para representar conceptos generales (por ejemplo, Shape, Animal), que pueden utilizarse como clases base para clases concretas (por ejemplo, Circle, Dog).

No se pueden crear objetos de una clase abstracta (excepto para subobjetos base de una clase derivada de ella) y no se pueden declarar miembros de datos no estáticos cuyo tipo sea una clase abstracta.

Los tipos abstractos no pueden utilizarse como tipos de parámetros, como tipos de retorno de funciones, o como el tipo de una conversión explícita (nótese que esto se verifica en el punto de definición y llamada de función, ya que en el punto de declaración de función los tipos de parámetros y retorno pueden estar incompletos).

Se pueden declarar punteros y referencias a una clase abstracta.

struct Abstract
{
    virtual void f() = 0;  // virtual puro
}; // "Abstract" es abstracta
struct Concrete : Abstract
{
    void f() override {}   // virtual no puro
    virtual void g();      // virtual no puro
}; // "Concrete" no es abstracta
struct Abstract2 : Concrete
{
    void g() override = 0; // redefinidor virtual puro
}; // "Abstract2" es abstracta
int main()
{
    // Abstract a;   // Error: clase abstracta
    Concrete b;      // OK
    Abstract& a = b; // OK para referenciar base abstracta
    a.f();           // despacho virtual a Concrete::f()
    // Abstract2 a2; // Error: clase abstracta (el redefinidor final de g() es puro)
}

La definición de una función virtual pura puede ser proporcionada (y debe ser proporcionada si la virtual pura es el destructor ): las funciones miembro de la clase derivada pueden llamar a la función virtual pura de la base abstracta usando el id de función calificado. Esta definición debe ser proporcionada fuera del cuerpo de la clase (la sintaxis de una declaración de función no permite tanto el especificador puro = 0 como un cuerpo de función).

Realizar una llamada virtual a una función virtual pura desde un constructor o el destructor de la clase abstracta es comportamiento indefinido (independientemente de si tiene una definición o no).

struct Abstract
{
    virtual void f() = 0; // virtual pura
    virtual void g() {}   // virtual no pura
    ~Abstract()
    {
        g();           // OK: llama a Abstract::g()
        // f();        // comportamiento indefinido
        Abstract::f(); // OK: llamada no virtual
    }
};
// definición de la función virtual pura
void Abstract::f()
{
    std::cout << "A::f()\n";
}
struct Concrete : Abstract
{
    void f() override
    {
        Abstract::f(); // OK: llama a la función virtual pura
    }
    void g() override {}
    ~Concrete()
    {
        g(); // OK: llama a Concrete::g()
        f(); // OK: llama a Concrete::f()
    }
};

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 390 C++98 podría llamarse a un destructor virtual puro no definido se requiere una definición en este caso
CWG 2153 C++98 pure-specifier podría aparecer en declaraciones friend prohibido

Véase también