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

定义一种抽象类型,该类型无法实例化,但可用作基类。

目录

语法

一个 纯虚 函数是指其 声明符 采用以下语法的 虚函数

声明符 虚函数说明符  (可选) = 0

此处序列 = 0 被称为 纯说明符 ,它紧跟在 声明符 之后出现,或在可选的 虚函数说明符 override final )之后出现。

纯说明符 不能出现在成员函数定义或 友元 声明中。

struct Base
{
    virtual int g();
    virtual ~Base() {}
};
struct A : Base
{
    // 正确:声明三个成员虚函数,其中两个为纯虚函数
    virtual int f() = 0, g() override = 0, h();
    // 正确:析构函数也可以声明为纯虚函数
    ~A() = 0;
    // 错误:在函数定义上使用纯说明符
    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;      // 正确
    Abstract& a = b; // 允许引用抽象基类
    a.f();           // 虚函数调用至 Concrete::f()
    // Abstract2 a2; // 错误:抽象类(g() 的最终重写是纯虚函数)
}

纯虚函数的定义可以被提供(且当纯虚函数是 析构函数 时必须提供):派生类的成员函数可以通过限定函数标识符自由调用抽象基类的纯虚函数。此定义必须在类体外部提供(函数声明的语法不允许同时使用纯说明符 = 0 和函数体)。

在抽象类的构造函数或析构函数中对纯虚函数进行虚调用是未定义行为(无论该函数是否具有定义)。

struct Abstract
{
    virtual void f() = 0; // 纯虚函数
    virtual void g() {}   // 非纯虚函数
    ~Abstract()
    {
        g();           // 正确:调用 Abstract::g()
        // f();        // 未定义行为
        Abstract::f(); // 正确:非虚调用
    }
};
// 纯虚函数的定义
void Abstract::f()
{
    std::cout << "A::f()\n";
}
struct Concrete : Abstract
{
    void f() override
    {
        Abstract::f(); // 正确:调用纯虚函数
    }
    void g() override {}
    ~Concrete()
    {
        g(); // 正确:调用 Concrete::g()
        f(); // 正确:调用 Concrete::f()
    }
};

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 适用范围 发布时行为 正确行为
CWG 390 C++98 未定义的纯虚析构函数可能被调用 此情况下需要提供定义
CWG 2153 C++98 pure-specifier 可出现在友元声明中 已禁止

参见