抽象クラス (C++ のみ)
抽象クラス とは、 特に基底クラスとして使用するように設計されたクラスです。 抽象クラスには、少なくとも 1 つの純粋仮想関数 が含まれています。 クラス宣言の中の仮想メンバー関数の宣言で、純粋指定子 (= 0) を使用することによって、純粋仮想関数を宣言することができます。
次に抽象クラスの例を示します。
class AB {
public:
virtual void f() = 0;
};
関数 AB::f は、純粋仮想関数です。
関数宣言に、純粋指定子と定義の両方を入れることはできません。
例えば、コンパイラーは以下のコードを許可しません。
struct A {
virtual void g() { } = 0;
};
抽象クラスをパラメーター型、関数からの戻りの型、または明示型変換の型として使用することはできませんし、
抽象クラスのオブジェクトも宣言することはできません。
ただし、抽象クラスを指すポインター、および参照を宣言することは可能です。
次の例は、このことを示しています。struct A {
virtual void f() = 0;
};
struct B : A {
virtual void f() { }
};
// Error:
// Class A is an abstract class
// A g();
// Error:
// Class A is an abstract class
// void h(A);
A& i(A&);
int main() {
// Error:
// Class A is an abstract class
// A a;
A* pa;
B b;
// Error:
// Class A is an abstract class
// static_cast<A>(b);
}
クラス A は、抽象クラスです。
コンパイラーは、関数宣言 A g() または void h(A)、
オブジェクト a の宣言、そして b の型 A への静的キャストも許可しません。仮想メンバー関数は、継承されます。 派生クラスにある各純粋仮想関数をオーバーライドしない限り、 抽象基底クラスから派生するクラスも抽象になります。
以下に例を示します。
class AB {
public:
virtual void f() = 0;
};
class D2 : public AB {
void g();
};
int main() {
D2 d;
}
コンパイラーは、オブジェクト d の宣言を許可しません。 D2 が、AB から純粋仮想関数 f() を継承した抽象クラスだからです。 関数 D2::f() を定義すると、コンパイラーは、オブジェクト d の宣言を許可します。これが、継承された純粋仮想関数 AB::f() をオーバーライドするからです。 D2 の抽象化を避けたい場合には、 関数 AB::f() をオーバーライドする必要があります。
非抽象クラスから抽象クラスを派生させたり、 非純粋仮想関数を純粋仮想関数でオーバーライドできることに注意してください。
抽象クラスのコンストラクターまたはデストラクターから、メンバー関数を呼び出すことができます。
ただし、コンストラクターから純粋仮想関数を呼び出した (直接または間接) 結果は、未定義です。
次の例は、このことを示しています。
struct A {
A() {
direct();
indirect();
}
virtual void direct() = 0;
virtual void indirect() { direct(); }
};
A のデフォルトのコンストラクターは、直接的、および間接的
(indirect() を介して) の両方で、純粋仮想関数 direct() を呼び出します。