名前空間
変種
操作

抽象クラス

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

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

目次

[編集] 構文

純粋仮想関数は、仮想関数であり、その宣言子は次の構文を持ちます。

宣言子 virt-指定子(オプション) = 0

ここで、シーケンス = 0純粋指定子として知られており、宣言子の直後、またはオプションのvirt-指定子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 {}
};

抽象クラスとは、最終的なオーバーライダ純粋仮想である関数を少なくとも1つ定義するか、継承するクラスです。

[編集] 説明

抽象クラスは、具体的なクラス(例:Circle、Dog)の基底クラスとして使用できる一般的な概念(例:Shape、Animal)を表すために使用されます。

抽象クラスのオブジェクトは作成できません(そこから派生したクラスの基底サブオブジェクトを除く)。また、型が抽象クラスである非静的データメンバーを宣言することもできません。

抽象型は、パラメータ型、関数戻り値型、または明示的な変換の型として使用できません(これは定義時および関数呼び出し時にチェックされます。関数宣言時ではパラメータ型と戻り値型は不完全である可能性があるためです)。

抽象クラスへのポインタと参照は宣言できます。

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++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 390 C++98 未定義の純粋仮想デストラクタが呼び出される可能性がある この場合、定義が必要である
CWG 2153 C++98 純粋指定子はフレンド宣言に現れる可能性がある 禁止された

[編集] 関連項目

English 日本語 中文(简体) 中文(繁體)