C++ で継承したときにサブクラスのメンバ関数を呼ぶためには virtual をつけて仮想関数にする
いや,このネタは半年くらい前に学んだ話の超初歩だと思うんですけど.
C++ で Factory Method について書こうと思ったときに,とりあえずここからまとめておこうかと.
ようするに,A というクラスを継承した B や C があって,そいつらを使うときには,型 A で変数を宣言するとします.そして,そのときに A に存在するメンバ関数を B などでオーバーライドしたい場合.同じ名前のメンバ関数を作ればオーバーライドされるわけではなくて,仮想関数として明示的に宣言してあげなきゃだめ.
#include <iostream> using namespace std; class Hoge { public: Hoge() {} ~Hoge() {} void Hello() {} }; class Fuga : public Hoge { public: Fuga() {} ~Fuga() {} void Hello() { cout << "Hello" << endl; } }; int main() { Hoge *a = new Fuga(); a->Hello(); delete a; }
としたときに,これでは実は a の Hello は Hoge のほうだけ見てちゃってて,Fuga の Hello が呼ばれない.
なので,Hogeの定義を
class Hoge { public: Hoge() {} ~Hoge() {} virtual void Hello() {} };
としてあげるといい.
あ,どういう原理(内部的に)でこうなるんだっけ.関数のバインドが実行時だから実行時にサブクラスへのポインタを保持するかみたいなテーブルがあるんだっけ.わすれた.あとで調べ...る?
あと,サブクラスのインスタンス化をしたときに,基底クラスのコンストラクタを呼ぶようにするには,
class Fuga : public Hoge { public: Fuga() : Hoge() {} ~Fuga(){} void Hello() { cout << "Hello" << endl; } };
としなきゃだめとか.
C++は色々あるよね.いや,というよりも,ある意味基底クラスの作成者の想定したメンバ関数しかオーバーライドできないってことですね.他のオブジェクト指向言語だと,なんだろ,基本的にはオーバーライド可能で,サブクラスでオーバーライドさせたくない場合には final つけるとか.そんなかんじかなあ.どっちがいいんだか?