抽象类
来自 cppreference.cn
定义一个不能被实例化但可作为基类的抽象类型。
目录 |
[编辑] 语法
声明符 虚说明符 (可选) = 0 |
|||||||||
这里的序列 = 0
被称为 纯说明符,它出现在 声明符 之后,或在可选的 虚说明符(override
或 final
)之后。
纯说明符 不能出现在成员函数定义或 友元 声明中。
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 {} };
一个 抽象类 是一个类,它定义或继承了至少一个函数,该函数的 最终覆盖器 是 纯虚 的。
[编辑] 解释
抽象类用于表示通用概念(例如,形状、动物),它们可以作为具体类(例如,圆形、狗)的基类。
不能创建抽象类的对象(除了从它派生的类的基子对象),也不能声明类型为抽象类的非静态数据成员。
抽象类型不能用作参数类型、函数返回类型或显式转换的类型(请注意,这在定义和函数调用点进行检查,因为在函数声明点,参数和返回类型可能不完整)。
可以声明指向抽象类的指针和引用。
运行此代码
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) }
可以提供纯虚函数的定义(如果纯虚函数是析构函数,则必须提供):派生类的成员函数可以使用限定函数ID自由地调用抽象基类的纯虚函数。此定义必须在类体之外提供(函数声明的语法不允许同时存在纯说明符= 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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
CWG 390 | C++98 | 可能调用未定义的纯虚析构函数 | 在这种情况下需要提供定义 |
CWG 2153 | C++98 | 纯说明符 可能出现在友元声明中 | 已禁止 |