C++ Builder XE4, 10.2 Tokyo > TForm > 複数のフォームのコンストラクタとOnCreate()の実行順番


動作環境
C++ Builder XE4
RAD Studio 10.2 Tokyo Update 2 (追記: 2018/01/05)

一つのユニットの処理を、将来の保守容易性のために複数のユニットで処理するように変更している。
その作業の結果、以下のエラーが出るようになった。

原因を追うと、一つのユニットのコンストラクタが動く前に、別のユニットのOnCreate()が動き、変数の初期化がされる前に使用されていることが分かった。

確認のため、三つのフォームに関して、コンストラクタとOnCreate()の実行順番を見てみる。

code

Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    String msg = L"Form1 ctor " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz");
    OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    String msg = L"Form1 OnCreate " + Now().FormatString(L"yyyy/mm/dd hh:nn:ss.zzz");
    OutputDebugString(msg.c_str());
}
//---------------------------------------------------------------------------

Unit2とUnit3も同様に実装した。

結果

デバッグ出力: Form1 ctor 2017/11/07 18:26:07.829 プロセス Project1.exe (4824)
デバッグ出力: Form1 OnCreate 2017/11/07 18:26:07.830 プロセス Project1.exe (4824)
デバッグ出力: Form2 ctor 2017/11/07 18:26:07.835 プロセス Project1.exe (4824)
デバッグ出力: Form2 OnCreate 2017/11/07 18:26:07.836 プロセス Project1.exe (4824)
デバッグ出力: Form3 ctor 2017/11/07 18:26:07.843 プロセス Project1.exe (4824)
デバッグ出力: Form3 OnCreate 2017/11/07 18:26:07.844 プロセス Project1.exe (4824)

Form1のOnCreateにおいてForm2の処理を使うような実装をした場合、Form2のコンストラクタの前に実施されて、冒頭のエラーになる。

OnCreate()の処理を見直すか、コンストラクタでなく別の初期化処理を最初にコールするなどの対応はした方が良さそう。

実施した対応

OnCreate()の処理を一部やめて、メイン画面のOnShow()からコールするように変更した。

隠しフォームはOnShow()が実施されないため、OnShow()が実施されるメイン画面からコールする、という方法は時々使う。