Абстрактный класс
Определяет абстрактный тип, который нельзя создать, но можно использовать в качестве базового класса.
Синтаксис
Чистая виртуальная функция — это виртуальная функция, чей декларатор имеет следующий синтаксис:
declarator virt-specifier (optional) = 0 |
Здесь последовательность = 0 называется pure-specifier и располагается либо сразу после declarator, либо после необязательного virt-specifier (override или final).
pure-specifier не может использоваться в определении функции-члена или в объявлении friend.
struct Base
{
virtual int g();
virtual ~Base() {}
};
struct A : Base
{
// OK: declares three member virtual functions, two of them pure
virtual int f() = 0, g() override = 0, h();
// OK: destructor can be pure too
~A() = 0;
// Error: pure-specifier on a function definition
virtual int b() = 0 {}
};
Абстрактный класс — это класс, который определяет или наследует по крайней мере одну функцию, для которой окончательная переопределяющая функция является чистой виртуальной.
Пояснение
Абстрактные классы используются для представления общих понятий (например, Shape, Animal), которые могут применяться в качестве базовых классов для конкретных классов (например, Circle, Dog).
Нельзя создавать объекты абстрактного класса (за исключением базовых подобъектов класса, производного от него), а также объявлять нестатические члены данных, тип которых является абстрактным классом.
Абстрактные типы нельзя использовать в качестве типов параметров, типов возвращаемых значений функций или типов явных преобразований (обратите внимание, что это проверяется в точке определения и вызова функции, поскольку в точке объявления функции типы параметров и возвращаемого значения могут быть неполными).
Можно объявлять указатели и ссылки на абстрактный класс.
struct Abstract
{
virtual void f() = 0; // pure virtual
}; // "Abstract" is abstract
struct Concrete : Abstract
{
void f() override {} // non-pure virtual
virtual void g(); // non-pure virtual
}; // "Concrete" is non-abstract
struct Abstract2 : Concrete
{
void g() override = 0; // pure virtual overrider
}; // "Abstract2" is abstract
int main()
{
// Abstract a; // Error: abstract class
Concrete b; // OK
Abstract& a = b; // OK to reference abstract base
a.f(); // virtual dispatch to Concrete::f()
// Abstract2 a2; // Error: abstract class (final overrider of g() is pure)
}
Определение чистой виртуальной функции можно предоставить (и его необходимо предоставить, если чистая виртуальная функция является деструктором): функции-члены производного класса могут вызывать чистую виртуальную функцию абстрактного базового класса с помощью квалифицированного идентификатора функции. Это определение необходимо предоставить вне тела класса (синтаксис объявления функции не допускает одновременного использования спецификатора чистой виртуальности = 0 и тела функции).
Вызов чистой виртуальной функции через виртуальный вызов из конструктора или деструктора абстрактного класса приводит к неопределённому поведению (независимо от того, имеет ли функция определение).
struct Abstract
{
virtual void f() = 0; // pure virtual
virtual void g() {} // non-pure virtual
~Abstract()
{
g(); // OK: calls Abstract::g()
// f(); // undefined behavior
Abstract::f(); // OK: non-virtual call
}
};
// definition of the pure virtual function
void Abstract::f()
{
std::cout << "A::f()\n";
}
struct Concrete : Abstract
{
void f() override
{
Abstract::f(); // OK: calls pure virtual function
}
void g() override {}
~Concrete()
{
g(); // OK: calls Concrete::g()
f(); // OK: calls Concrete::f()
}
};
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение согласно опубликованному стандарту | Корректное поведение |
|---|---|---|---|
| CWG 390 | C++98 | неопределённая чистая виртуальная функция-деструктор могла быть вызвана | в этом случае требуется определение |
| CWG 2153 | C++98 | pure-specifier мог использоваться в объявлениях friend | запрещено |
См. также
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/abstract_class