C++におけるvirtual(仮想関数)の使い方を紹介していく
今回は、C++を使う上で重要になるvirtual
(仮想関数)について解説していきます。
virtualとは何か?
virtualとは何かを理解するためには、virtualがいつ、どのような時に使われるかを理解した方が早いです。
例えば、以下のコードを見てください。以下のコードは、Base
クラスとChild
クラスにfunc()
関数が定義されており、Base
クラスのポインタを通してそれぞれのfunc
関数を呼び出しています。
#include <iostream> using namespace std; class Base { public: void func(){ cout << "this is Base" << endl; } }; class Child: public Base { public: void func(){ cout << "this is Child" << endl; } }; int main() { Base *p; Base b; Child c; p = &b; p->func(); p = &c; p->func(); return 0; }
上のコードでは、まずBase
クラスのfuncが呼び出されて次にChild
クラスのfuncが呼び出されることを期待しますが、結果は以下の様になってしまいます。
this is Base this is Base
これは、ポインタから関数を呼び出すときには、コンパイラはポインタの型を見て、そのポインタの型のクラスの関数を呼び出そうとするからです。今回の例では、ポインタはBase *p;
と定義されているので、p = &c; p->func();
としてもBase
クラスのfunc関数を呼び出してしまうのです。
しかし、Baseクラスのfunc関数の先頭にvirtual
と書いてあげることで、期待通りの動きをしてくれます。
class Base { public: virtual void func(){ cout << "this is Base" << endl; } };
this is Base this is Child
これはvirtual
キーワードを付けることで、virtualの関数がポインタを通して呼ばれた時に、コンパイラはそのポインタ先のオブジェクトを見てどのクラスの関数を呼ぶかを決めるようになるからです。
virtualの使いどころってあるの?
上記の説明を見ると「仮想関数って、あまり使い道なくない?」と感じますが、仮想関数は主にインターフェースを実装するために使われることが多いです。PHPなどではインタフェースは言語がサポートしていますが、C++ではサポートされていないので、仮想関数を使う事で疑似的にインターフェースを実現します。
先ほどのBase
クラスをインターフェースに修正したい場合は、以下の様に書きます。
class Base { public: virtual void func() = 0; };
重要なのは、関数をvirtual void func() = 0;
のように書くこと。