ホームに戻る
関連 :
継承 (Inheritance) 仮想デストラクタ 委譲コンストラクタと継承コンストラクタ 関数オーバーロードとデフォルト引数 C++11
目次 :

仮想関数とは

基本クラスで定義され、派生クラスで再定義されるメンバ関数のこと。
基本クラスと異なる処理を実装する、または基本クラスでは概念のみを定義しておき、派生クラスで具体化するということができる。
C++に限らず、オブジェクト指向言語では一般的な概念。継承とともにオブジェクト指向の根幹をなす。
画像

重要な前提 : 派生クラスと基本クラスのポインタ

基本クラスと派生クラスが存在する場合、 基本クラスのポインタは、その基本クラスから派生したすべてのクラスオブジェクトを指し示すことができる
// 基本クラス Vehicle class Vehicle { public: virtual void Accelarate(); : } // 派生クラス Car class Car : public Vehicle { : } // Vehicle 型ポインタが Car の実体を指す Vehicle* pOb_Vehicle; Car Ob_Car; pOb_Vehicle = &Ob_Car;
但し、(派生クラスオブジェクトを指す) 基本クラスポインタを用いてアクセスできるのは、基本クラスに存在するメンバのみである
(派生クラスで新たに追加したメンバは、基本クラスポインタを用いてアクセスすることはできない。キャストを用いて強引に行うことは不可能ではないが、推奨されない。)
仮想関数も例外ではないが、 基本クラスに存在する仮想関数を派生クラスで再定義しているため
(派生クラスオブジェクトを指す)基本クラスポインタを用いて仮想関数にアクセスすると、 派生クラスで再定義した仮想関数が正しく呼び出される
(基本クラスの関数を呼び出すわけではない。)

仮想関数の定義

// 基本クラス Vehicle class Vehicle { public: // 仮想関数 Accelarate() の定義 : 基本クラス virtual void Accelarate() { : } : } // 派生クラス Car class Car : public Vehicle { public: // 仮想関数 Accelarate() の定義 : 派生クラス ⇒ virtual キーワードは不要 void Accelarate() { : } : } // 派生クラス Motorcycle class Motorcycle : public Vehicle { public: // 仮想関数 Accelarate() を定義しない ⇒ Vehicle の Accelarate() を使用 : }

関数を再定義(上書き)することを 「オーバーライド (Override)」 と呼ぶ。
仮想関数のオーバーライドの際は、 基本クラスでの定義と引数の型・数、戻り値の型がすべて一致していなければならない
(オーバーロードとの混同に注意。オーバーロードは逆に、引数の型・数のいずれかが異なっていなければならない。)
なお、オーバーライド時に virtual キーワードは必須ではない。virtual キーワードを省いても関数の仮想性は引き継がれる。

仮想関数の用途 : 実行時ポリモーフィズム

上述の通り、基本クラスのポインタが派生クラスのオブジェクトを指すことができるため、以下のような実装が可能。
void Drive(int i) { Car Ob_Car; //< Car 型オブジェクト Motorcycle Ob_Motorcycle; //< Motorcycle 型オブジェクト Vehicle* pOb_Vehicle; //< 基本クラス Vehicle 型ポインタ pOb_Vehicle = ( i == 0) ? &Ob_Car : &Ob_Motorcycle; pOb_Vehicle->Accelarate(); }

ここで、i の値はプログラムを実行するまで確定しない(コンパイル時に決定できない)ため、pOb_Vehicle が Ob_Car と Ob_Motorcycle のいずれを指すかは実行時までわからない。
しかし、Accelarate() を基本クラスで仮想関数として定義しておけば、基本クラスポインタがいずれの派生クラスを指す場合でも、インタフェース(Accelarate() のコール)を変更する必要が無い。
(pOb_Vehicle が Ob_Car を指す場合は Car の、Ob_Motorcycle を指す場合は Motorcycle の Accelarate() が実行される。)
pOb_Vehicle はプログラムの実行時に、Car 、Motorcycle いずれのポインタとしても振舞うことができる(多態)。
この性質を「 実行時ポリモーフィズム 」と呼び、派生クラスとしても振舞えることから、(仮想関数を有する)基本クラスを「 ポリモーフィッククラス 」と呼ぶ。
尚、実行時ポリモーフィズムの実現に当たっては注意が必要。仮想デストラクタを参照のこと。

純粋仮想関数

基本クラスでは仮想関数に有意な処理を実装せずにインタフェース(引数・戻り値)のみを規定し、派生クラスで具体的な処理を実装することができる。
このような実体の無い仮想関数を 「純粋仮想関数(Pure Virtual Function)」 と呼ぶ。一般形は以下の通り。
ここで、