仮想関数

最終更新日03 Jul 2017 12:23

意味

may be redefined later in a class derived from this one

(この関数は)あとでこのクラスを継承する子クラスで再定義しますよ、という意味
virtualをつけた関数は、このクラスとこのクラスから派生したクラスで定義された関数のinterfaceとして機能することを示す。
仮想メンバ関数のことをmethodと呼ぶこともある[2]

=0

=0がついてると、このクラスから継承した子クラスは必ずこの関数を定義しなくてはならない。
と、いう意味になる。

仮想関数には、派生クラスで再定義できる、という利点があります。
基底クラスの仮想関数を派生クラスで再定義することをオーバーライドといいます。
(javaのオーバーライドと少し違うかな。と思ったけど
Java では、クラスのすべてのメソッドは仮想関数です。

どんな時に使う? デストラクタには必ずつけるのが吉

デストラクタでは主に、リソースの解放とかを行う。
普通、リソースって、親クラスじゃなくて、子クラスが(より多く)持ってるよね?
なので、デストラクタにはvirtualをつけて、必ず確実に呼び出されるようにするのは吉です。

定義

基本クラスのメンバ関数を再定義することができます
このような関数を仮想関数と呼びます
仮想関数は、必ずしも再定義しなければならないものではありません
必要がなければ再定義しなくても良い

仮想関数のパフォーマンス

普通の関数より、遅い[1]らしい。

遅い理由

呼び出されるコードは、それぞれの関数呼び出しだけでなく、関数が呼び出される時のオブジェクトの型にも依存する。
通常、これは仮想関数テーブル(vtable)を使うことで解決する。

純粋仮想関数との違い

非仮想関数関数 一般(不純)仮想関数 純粋仮想関数
作り方 void method(); virtual void method(); virtual void method()=0;
関数の再定義 できない してもしなくてもいい 必ずしなくてはならない
中身 書いてもいい 書いてもいい 何も書かない
クラス 普通のクラス  親クラス 抽象クラス,インターフェース
意味 インタフェース実装の両方を継承せよ インターフェイス継承せよという意味になる。

virtualをつけずに親クラスと同じ名前の関数を書いたらどうなるか?
自分がオーバーライドしたつもりの関数の中身は呼び出されず、親クラスの内容が呼び出される

エラー virtual関数を引き継いでないと実態がないといわれる

=0にしなければ、「オーバーライドしてもしなくてもいい」はずなのになんで?
なぜかvirtualつきのデストラクタを作ったら治った。→基底クラス参照

一般仮想関数を宣言する目的

派生クラスに関数のインタフェースデフォルトの実装を継承させること。
つまり、

virtual error();

だったら、
「私を継承するすべてのクラスは、エラーが起きた時によびだされる 関数をサポートしなければならないが、
エラーをどのように処理するかは、それぞれのクラスで自由に決めて構わない。」
特別なエラー処理を行わないクラスは、親クラスが提供するデフォルトのエラー処理をそのまま使えばいい。

一般仮想関数の欠点

一般仮想関数つきの親クラスを継承した子クラスは、
親クラスの一般仮想関数を
別に継承したい!と意思を表明しなくても勝手に継承してしまう点にある。

この欠点を補うには?

一般関数でデフォルトの振る舞いをする関数defaultFunction()みたいに宣言して、
必ず純粋仮想関数Function()をセットにすることだ。
デフォルトの振る舞いでいいって思ってる派生クラスは

void Function(){defaultFunction();}

てそのまま書けばいいし、
自分は特別な振る舞いをしたい!と思ってる派生クラスはFunctionに独自の振る舞いを記述すればいい。
そういうデフォルトの振る舞いをする関数にはprotected修飾子をつけるといいらしい。

デフォルトパラメータ付きの仮想関数

仮想関数動的に結合されるが
デフォルトパラメータ静的に結合される。
仮想関数を呼び出すと、実際に呼び出されるのは派生クラスで定義された関数だが、
そのデフォルトパラメータには基底クラスの値が使われる。
混乱の元である。
だから、継承クラスでは仮想関数のデフォルトパラメータ値を再定義してはならない

virtual関数が一個でもあるとpolymorphic baseになる

コードの書きかけで、virtual関数を一個も持っていない親クラスを作った。
そしたら子クラスが呼ばれなくて挙動が変だった。
どうやらvirtual関数が一個もないとnon-polymorphic baseとみなされてstatic typeになるらしい[5]
このstatic typeってどんな時に用途があるんだ??


ファイル

サポートサイト Wikidot.com