main()の隠蔽
小ネタ.
main()からプログラムを書き始めると,大した規模でないものでも,
物凄くプログラムを書いた感じがして,どっと疲れる.
自分は,元々Windowsプログラムは楽チンMFCから入った人間なので,多分,
main()から書き始めるプログラムは,何か大変っていう刷り込みがあるっぽい.
# 逆にmain()から書き始めないプログラムは,何か心許ないというのも分かる.
そんな訳で,main()の隠蔽方法についてメモ.
C++では,グローバル変数として宣言したインスタンスのコンストラクタが,
main()より前に呼ばれる(っぽい)のを利用して,main()を隠蔽してた.
このやり方は MFC と同じ.(簡単な実例は SpeedShooter ソース参照)
//-------------------------------------------------- // アプリケーションの基底クラス //-------------------------------------------------- class CMainApp { public: static CMainApp* s_pMainInstance; public: CMainApp() { s_pMainInstance = this; } virtual int Body()=0; }; CMainApp* CMainApp::s_pMainInstance = NULL; //-------------------------------------------------- // main 関数 //-------------------------------------------------- int main(int argc, char* argv[]) { return CMainApp::s_pMainInstance->Body(); } //-------------------------------------------------- // ここから実装 //-------------------------------------------------- class CApp : public CMainApp { public: int Body() { ...(メインプログラム)... } }; // 実装したクラスのインスタンスをグローバル変数にすると, // main()より前に CMainApp::CMainApp() が呼ばれて // s_pMainInstance に実装したインスタンスのポインタが渡る. CApp theApp;
Dだとインスタンスの生成には必ず new 文を使わないといけないっぽいので,
実行中に,どっかでインスタンスの生成を行わないといけないっぽい.
# ↑未確認.「静的インスタンス」みたいのって無いのかな?
で,リファレンスを読んでたんだけど,どうも「静的コンストラクタ」という
のが用意されているらしい.
>静的コンストラクタは、 main() に制御が移る前に初期化を実行する関数として
>定義されています。静的コンストラクタは、クラスの静的メンバを、
>コンパイル時には計算できない値で初期化する際に使用します。
よするに,プログラム中,最初から最後まで居座るインスタンスを作るような場合,
静的コンストラクタの中で new しろって事?
要はmain()より前に,実装したクラスのインスタンスが渡せれば良いので,
静的コンストラクタ内で自分のインスタンスを new して渡す事にしてみる.
//-------------------------------------------------- // アプリケーションの基底クラス //-------------------------------------------------- abstract class CMainApp { public: static CMainApp s_MainInstance; public: static void boot(CMainApp app) { s_MainInstance = app; } int Body() { return 0; } }; //-------------------------------------------------- // main 関数 //-------------------------------------------------- int main(char argv[][]) { return CMainApp.s_MainInstance.Body(); } //-------------------------------------------------- // ここから実装 //-------------------------------------------------- class CApp : public CMainApp { public: // 静的コンストラクタ内で自分インスタンスを生成させて, // 実装したインスタンスのポインタを s_MainInstance に渡す. static this() { boot(new CApp); } int Body() { ...(メインプログラム)... } };
まだ,簡単な実験しかしてないけど,一応うまく行きそう.
グローバルなインスタンスのコンストラクタみたいに,曖昧な位置でなく,
明示的に「main() に制御が移る前に」実行される場所があるってのは良いかも.
ただ,実行順についてはかなり慎重に書かないといけなそうだけど.
あと,static メンバを2回記述しなくて済むのが素晴らしいな.