
![]() |
|||
|
ポリモーフィズムを実現するには、スーパークラスと同じ形式のメソッドを定義し、これを仮想関数にします。またデストラクタも仮想関数にします。そしてスーパークラスの型のポインタを通してアクセスします。 |
|||
![]() |
|||
| このトピックでは次の用語を覚えます: | |||
|
|||
![]() |
|||
|
前のトピックで「留守番電話」クラスの例題をとりあげました。そのサンプルコードの中に、virtual というキーワードがありましたが、これはポリモーフィズムを表現するためのものです。virtual な関数のことを仮想関数と呼びます。 |
|||
|
||||
|
上のコードは前のトピックで掲載したものと同じです。これは「電話」クラス(「留守番電話」のスーパークラス)の宣言ですが、2カ所に virtual が使用されています。 |
|||
|
ひとつは 重要なのは、「留守番電話」クラスにもまったく同じインターフェイスのメソッドがあって、その動作が異なる点です。しかしどちらも「電話」 の一種であり、メソッドを実行する側では同じように扱うことができます。メソッドを実行する側では、たとえば次のようになります。スーパークラス(Phone)型のポインタを通して操作している点に注目してください。C++ ではこのようにすることで、ポリモーフィックなメソッド呼び出しを実現します。 |
|||
|
||||
|
この |
|||
|
||||
| デストラクタを virtual にする | |||
|
「電話」クラスでもうひとつ仮想関数になっているものがありました。それはデストラクタ ポリモーフィックなオブジェクトはスーパークラスのインスタンスであるかのように扱われることは上述した通りです。「留守番電話」オブジェクトを new で確保し、これを「電話」クラス型のポインタを通して delete する場合を考えてください。デストラクタが virtual でない場合、これだと「電話」クラス用のデストラクタが呼び出されてしまいます。 このような不都合を避けるため、「電話」クラスのデストラクタを仮想関数にする必要があるのです。そうするとデストラクタの「連鎖」が起こり、「電話」クラス型のポインタを通して delete した場合でもサブクラス側のデストラクタからスーパークラス側のデストラクタへと順番に呼び出されていきます。これはちょうどコンストラクタの連鎖と逆の動作です。コンストラクタはスーパークラス側からサブクラス側へ向かって呼び出されていきます。 |
|||
|
賢明な方なら「すべてのメソッドが仮想関数になればいいのに」と思うかもしれません。しかし C++ では virtual キーワードをつけたメソッドだけが仮想関数になります。Java では何もつけなくてもすべてのメソッドが仮想関数です。 これは、実行時の速度効率を考慮しているのです。仮想関数の呼び出しは「ダイナミックバインディング」と言って、実行時にはじめてどのクラスのメソッドを呼ぶのかが決定されるため、通常のメソッド呼び出しより時間的なコストがかかるのです(ほんの少しだけですが)。速度を犠牲にしたくないプログラマのために、C++ では仮想関数にするかどうかが細かく選べるようになっているというわけです。 |
|||
| もっと詳しく知りたい人は次の用語について調べると良いでしょう: | ||||
|
||||
(「オブジェクト指向のはなし」は1999年2月から2000年4月にかけて作成されたコンテンツです。)