抽象クラス

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::g() を定義すれば、コンパイラーは、 オブジェクト d の宣言を行うことができます。

非抽象クラスから抽象クラスを派生させたり、 非純粋仮想関数を純粋仮想関数でオーバーライドできることに注意してください。

抽象クラスのコンストラクターまたはデストラクターから、メンバー関数を呼び出すことができます。 ただし、コンストラクターから純粋仮想関数を呼び出した (直接または間接) 結果は、未定義です。 次の例は、このことを示しています。

struct A {
  A() {
    direct();
    indirect();
  }
  virtual void direct() = 0;
  virtual void indirect() { direct(); }
};

A のデフォルトのコンストラクターは、直接的、および間接的 (indirect() を介して) の両方で、純粋仮想関数 direct() を呼び出します。

コンパイラーは、純粋仮想関数の直接呼び出しには警告を出しますが、間接呼び出しには警告を出しません。

関連参照

IBM Copyright 2003