数年来、気になっていたことがやっとわかったのでブログにアップしてみる。
Windowsには、MFCというアプリケーションフレームワークがある。これは、MVCモデルに基づいた、Windowsアプリケーションの構築における構造(アーキテクチャ)の定義(ようするに狭義のフレームワーク)と、クラスライブラリの集まり(ようするに広義のフレームワーク)である。
ところで、MFCとは別に、Windows SDKというWindowsアプリケーションを構築するための開発キットがある。これが、Windows APIと呼ばれるものだが、これには、windows.hというヘッダーファイルが含まれており、これをインクルードすることによって、本来、main関数から実行されるC言語のプログラムは、WinMainという関数から実行されるようになる。
さて、MFCは、このWindows SDKに基づいて、GUIアプリケーションの生産性を向上させるためのフレームワークであるが、MFCのアプリケーションウィザードでGUIアプリケーションのスケルトンを作ったときに、main関数はともかく、WinMainすら見えなくなる。Cの、ポインタ返り(挫折のきっかけ)と同じように、この現象の理由を理解しようとせずに、MFCから離れていく人を多く見てきた。
MFCアプリケーションには、おおむねMFCxx.DLLというライブラリがカレントディレクトリかシステムディレクトリになければ実行できないが、このライブラリの中にすでにWinMainがいて、このWinMainが、MFCの唯一のアプリケーションインスタンスである、CWinAppクラスの派生クラスのInitInstanceメソッドを呼び出しているというのが答えである。
さて。
ここまでは、使い古された議論であるが、数年来、気になっていたのは、MFCアプリケーションは、どうやって対象のCWinAppの派生クラスを探しているのか、ということである。ずっと、自分のなかにあるクラスを走査して、CWinAppクラスの派生クラスが見つかったらそれをインスタンス化するもんだとばかり思っていた。だから、同じプロジェクトにCWinAppクラスの派生クラスが1つより多くあると、コンパイルが通らないと思っていたのだが、コンパイルは通る。
で。
あとから追加したCWinAppの派生クラスと、アプリケーションウィザードによって追加されたCWinAppの派生クラスの内容を入れ替えて実行してみると、これまで後者のInitInstanceが呼び出されていたのが、前者のInitInstanceが呼ばれるように変わった。…なるほど、なんかマクロかなにか書いてあるのかな、と思ったら、それらしいのは、
CHogehogeApp theApp;
という記述。この記述だけを、別のCWinAppの派生クラスに動かすと、やっぱりそちらのInitInstanceが動くようになった。
えー
グローバル変数だったの?。。。しかも固定だし。。。ザ・エーピーピー、否、ジ・エーピーピー。
これも使い古された議論かな。MFC自体と、MFCが単にAPIをラップしただけのクラスライブラリであるという議論と同じように。
ごきげんよう。