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

Определяет абстрактный тип, который не может быть инстанцирован, но может использоваться как базовый класс.

Содержание

Синтаксис

Чисто виртуальная функция — это виртуальная функция , чей декларатор имеет следующий синтаксис:

declarator virt-specifier  (необязательно) = 0

Здесь последовательность = 0 известна как pure-specifier и появляется либо непосредственно после declarator , либо после опционального virt-specifier ( override или final ).

pure-specifier не может появляться в определении функции-члена или friend объявлении.

struct Base
{
    virtual int g();
    virtual ~Base() {}
};
struct A : Base
{
    // OK: объявляет три виртуальные функции-члена, две из них чисто виртуальные
    virtual int f() = 0, g() override = 0, h();
    // OK: деструктор также может быть чисто виртуальным
    ~A() = 0;
    // Ошибка: спецификатор pure-specifier в определении функции
    virtual int b() = 0 {}
};

Абстрактный класс — это класс, который либо определяет, либо наследует по крайней мере одну функцию, для которой конечный переопределитель является чисто виртуальной функцией .

Объяснение

Абстрактные классы используются для представления общих концепций (например, Shape, Animal), которые могут использоваться как базовые классы для конкретных классов (например, Circle, Dog).

Нельзя создавать объекты абстрактного класса (за исключением базовых подобъектов класса, производного от него), и нельзя объявлять нестатические члены данных, тип которых является абстрактным классом.

Абстрактные типы не могут использоваться в качестве типов параметров, типов возвращаемых значений функций или типов явных преобразований (обратите внимание, что это проверяется в точке определения и вызова функции, поскольку в точке объявления функции параметры и возвращаемый тип могут быть неполными).

Указатели и ссылки на абстрактный класс могут быть объявлены.

struct Abstract
{
    virtual void f() = 0;  // чисто виртуальная
}; // "Abstract" является абстрактным
struct Concrete : Abstract
{
    void f() override {}   // не чисто виртуальная
    virtual void g();      // не чисто виртуальная
}; // "Concrete" не является абстрактным
struct Abstract2 : Concrete
{
    void g() override = 0; // чисто виртуальный переопределитель
}; // "Abstract2" является абстрактным
int main()
{
    // Abstract a;   // Ошибка: абстрактный класс
    Concrete b;      // OK
    Abstract& a = b; // OK для ссылки на абстрактный базовый класс
    a.f();           // виртуальный вызов Concrete::f()
    // Abstract2 a2; // Ошибка: абстрактный класс (финальный переопределитель g() является чистым)
}

Определение чисто виртуальной функции может быть предоставлено (и должно быть предоставлено, если чисто виртуальной является деструктор ): функции-члены производного класса могут вызывать чисто виртуальную функцию абстрактного базового класса, используя квалифицированный идентификатор функции. Это определение должно быть предоставлено вне тела класса (синтаксис объявления функции не позволяет одновременно использовать чистый спецификатор = 0 и тело функции).

Вызов виртуальной функции для чистой виртуальной функции из конструктора или деструктора абстрактного класса является неопределенным поведением (независимо от того, имеет ли она определение или нет).

struct Abstract
{
    virtual void f() = 0; // чисто виртуальная
    virtual void g() {}   // не чисто виртуальная
    ~Abstract()
    {
        g();           // OK: вызов Abstract::g()
        // f();        // неопределённое поведение
        Abstract::f(); // OK: невиртуальный вызов
    }
};
// определение чисто виртуальной функции
void Abstract::f()
{
    std::cout << "A::f()\n";
}
struct Concrete : Abstract
{
    void f() override
    {
        Abstract::f(); // OK: вызов чисто виртуальной функции
    }
    void g() override {}
    ~Concrete()
    {
        g(); // OK: вызов Concrete::g()
        f(); // OK: вызов Concrete::f()
    }
};

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
CWG 390 C++98 an undefined pure virtual destructor might be called a definition is required in this case
CWG 2153 C++98 pure-specifier could appear in friend declarations prohibited

Смотрите также