C++の仮想関数(Virtual Function)とは?ポリモーフィズムを実現する仕組みを解説!
C++における「仮想関数(Virtual Function)」は、継承とポリモーフィズム(多態性)を実現するための重要な仕組みです。
クラスのメンバ関数に virtual
を付けることで、実行時に正しい関数が呼び出されるようになります。
この記事では、仮想関数の役割や使い方、通常の関数との違いを初心者向けにやさしく解説します。
仮想関数とは?
仮想関数とは、親クラスに定義された関数で、子クラスでオーバーライドされることを前提とした関数です。
通常の関数と違い、ポインタや参照を使ってオブジェクトを扱うとき、実行時(ランタイム)に正しい関数を呼び分けることができます。
仮想関数の基本構文
class 親クラス {
public:
virtual void 関数名(); // 仮想関数
};
class 子クラス : public 親クラス {
public:
void 関数名() override; // オーバーライド
};
仮想関数の使用例
#include <iostream>
using namespace std;
// 親クラス
class Animal {
public:
virtual void speak() {
cout << "動物が鳴いています。" << endl;
}
};
// 子クラス
class Dog : public Animal {
public:
void speak() override {
cout << "ワンワン!" << endl;
}
};
int main() {
Animal* animal = new Dog();
animal->speak(); // Dogのspeak()が呼ばれる
delete animal;
return 0;
}
この例では、Animal
クラスの speak()
に virtual
を付けることで、ポインタが親型でも、正しく子クラスの関数が呼ばれるようになります。
仮想関数を使うメリット
- ポリモーフィズムを実現できる
親クラス型のポインタで、複数の子クラスの動作を切り替えられる。
- 拡張性が高い
親クラスに手を加えず、新しい子クラスを追加できる。
- 共通インターフェースで柔軟な処理
異なるクラスでも同じ関数名で処理をまとめられる。
仮想関数と非仮想関数の違い
項目 | 仮想関数 | 通常の関数 |
キーワード | virtual | なし |
呼び出しのタイミング | 実行時に決定(動的バインディング) | コンパイル時に決定(静的バインディング) |
使い方 | オーバーライドを前提 | 基本的には固定処理 |
デストラクタは仮想にすべき?
はい、継承関係にあるクラスでは、親クラスのデストラクタは必ず仮想関数にすべきです。
そうしないと、子クラスのデストラクタが正しく呼ばれず、リソースリークの原因になることがあります。
class Animal {
public:
virtual ~Animal() {
cout << "Animalのデストラクタ" << endl;
}
};
まとめ
C++の仮想関数は、オブジェクト指向における「柔軟性」「拡張性」「汎用性」を実現する重要な要素です。
特に、継承やオーバーライド、ポリモーフィズムといった仕組みと深く関係しています。
関数に virtual
を付けることで、C++プログラムの設計は大きく進化します。ぜひ、実際にコードを書いて動的な関数の呼び分けを体験してみましょう!