C++で抽象クラスを実現する方法


Javaの場合はabstractキーワードで抽象クラスや、抽象メソッドを実現出来ましたが、C++にはそのようなキーワードがありません。ではどうするのかというと、C++では非常にユニークな記法を用います。

純粋仮想関数

C++で抽象クラスを実現するためにはvirtual 型 関数名() = 0;という形式で未実装の関数を宣言します。

struct Animal {
   virtual int type() = 0;
};

このような形式で宣言された関数は純粋仮想関数(pure virtual function)と呼ばれます。また純粋仮想関数が宣言されたクラスは自動的に抽象クラスとなります。

純粋仮想関数による抽象クラスの宣言

// 抽象クラス
struct Animal {
   virtual const char* makeSound() = 0; // 純粋仮想関数
   void say() { puts(makeSound()); }
};

// サブクラスで仮想関数をオーバーライド
struct Cat : Animal {
   const char* makeSound() { return "にゃー!"; }
};
struct Dog : Animal {
   const char* makeSound() { return "ワン!"; }
};

実行サンプル

int main(int argc, const char* argv[]) {
   Cat().say(); // "にゃー!"
   Dog().say(); // "ワン!"
   
   // 親クラスは抽象クラスになるため、インスタンス化が出来なくなる
   Animal animal; // Error: Variable type 'Animal' is an abstract class
   Animal();      // Error: Allocating an object of abstract class type 'Animal'
}

抽象クラス

純粋仮想関数が宣言されたクラスは自動的に抽象クラス(abstract class)とみなされ、上記サンプルのAnimalようにインスタンス化が行えなくなくなるという特徴があります。またサブクラス側ではメソッドの実装が必須となります

struct Dog : Animal {
   //const char* makeSound() override { return "ワン!"; }
};
// 純粋仮想関数を子クラス側で実装しないとエラーになる
Dog().say(); // Error: Allocating an object of abstract class type 
ただしサブクラスのインスタンス化を行わない場合は実装不要です。その場合サブクラスはスーパークラス同様に抽象クラスとみなされます。
// 実装しないとDogは連鎖的に抽象クラスとみなされ、
// 今度はその子クラス側で純粋仮想関数の実装が必要になる。
struct Pag : Dog {
   const char* makeSound() { return "おっ?"; }
};
Pag().say(); // "おっ?"

広告

関連するオススメの記事