抽象类
来自 cppreference.com
定义一个无法实例化的抽象类型,但可以作为基类使用。
内容 |
[编辑] 语法
声明符 virt-specifier (可选) = 0 |
|||||||||
这里,序列 = 0
被称为 pure-specifier,它出现在 声明符 之后,或者出现在可选的 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 声明中 | 禁止 |