抽象クラス
インスタンス化できないが、基底クラスとして使用できる抽象型を定義します。
目次 |
[編集] 構文
純粋仮想関数は、仮想関数であり、その宣言子は次の構文を持ちます。
宣言子 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 | 純粋指定子はフレンド宣言に現れる可能性がある | 禁止された |