Abstract class
Определяет абстрактный тип, который не может быть инстанцирован, но может использоваться как базовый класс.
Содержание |
Синтаксис
Чисто виртуальная функция — это виртуальная функция , чей декларатор имеет следующий синтаксис:
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 |