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

インスタンス化できないが、基底クラスとして使用できる抽象型を定義します。

目次

構文

pure virtual 関数は、 virtual関数 のうち、 declarator が以下の構文を持つものです:

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: 3つのメンバ仮想関数を宣言、うち2つは純粋仮想関数
    virtual int f() = 0, g() override = 0, h();
    // OK: デストラクタも純粋仮想にできる
    ~A() = 0;
    // エラー: 関数定義に対する純粋指定子
    virtual int b() = 0 {}
};

abstract class (抽象クラス)は、少なくとも1つの関数について the final overrider pure virtual (純粋仮想)であるクラスを定義または継承するクラスです。

説明

抽象クラスは一般的な概念(例えば、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)
}

純粋仮想関数の定義は提供可能である(また、純粋仮想関数が デストラクタ である場合は提供しなければならない):派生クラスのメンバ関数は、修飾された関数IDを使用して抽象基底クラスの純粋仮想関数を呼び出すことができる。この定義はクラス本体の外側で提供されなければならない(関数宣言の構文は純粋指定子 = 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 適用対象 公開時の動作 正しい動作
CWG 390 C++98 未定義の純粋仮想デストラクタが呼び出される可能性があった この場合、定義が必須
CWG 2153 C++98 pure-specifier がfriend宣言内に記述可能だった 禁止

関連項目