お世話になります。
現在、テスト的にクラスを作ってみました。
こんな感じです。
----------------------------------------
type
TTestClass = class(TObject)
private
public
constructor Create(AOwner: TObject);
destructor Destroy; override;
end;
TForm1 = class(TForm)
<<中略>>
end;
var
Form1: TForm1;
TestClass: TTestClass;
constructor TTestClass.Create(AOwner: TObject);
begin
inherited Create;
end;
destructor TTestClass.Destroy;
begin
inherited Destroy;
end;
----------------------------------------
これを使用するためにプロジェクトで以下のように使用しました。
----------------------------------------
begin
TestClass.Create(Application);
try
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
finally
TestClass.Free;
end;
end.
----------------------------------------
コンパイルは通ったのですが、
実行時にクラスの例外エラーがでます。
どうしてなのでしょうか?
クラスの目的
外部変数をまとめたものをクラス化し、
アプリケーションの開始時に作成します。
アプリケーション終了後にこれらを削除しようとしています。
プロジェクトではなく、上のユニット(TForm1のある方)で
initialization
TestClass := TTestClass.Create(Application);
finalization
TestClass.Free;
あと TComponent 派生クラス以外で Owner を設定してはいけません。
TObject 派生ならこの場合 Create; だけでコンストラクタはOK
どうも、お世話になりました。
プロジェクトの変更、ユニットの変更とも
教えられたとおりに変更するとうまくいきました。
でも、プロジェクトではなぜエラーになるのでしょうか?
Application.Initialize で initializationが実行されるんですよね。
で、実行されると finalization が最後に自動的に実行される
もののようですが、これって同じ処理ではないのですか?
以前DLL作ったときなんかでは同じようにして
うまくいっていたような気がするのですけど。
> プロジェクトではなぜエラーになるのでしょうか?
TestClass.Create(Application);
TestClass はまだインスタンスが作成されてないでしょ。ななしさんの
TestClass := TTestClass.Create(Application);
と比べてください。
コンスタラクタはクラス参照で使用します。
> Application.Initialize で initializationが実行されるんですよね。
これも違います。その前に実行されます。Application オブジェクトもそれで
作られているので Application.Initialize が実行できるのです。
あ、今気づきました。
以下のようにしなければいけなかったんです。
初歩的なミス(今まで気づかなかったです・・なさけない)してました。
begin
TestClass := TTestClass.Create(Application);
try
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
finally
TestClass.Free;
end;
end.
このやり方でも正常に動作はするのですが、
でも、プロジェクト部では initialization や finalization を使うほうが
一般的なのでしょうか?
initialization や finalization はちょっとなじめなくて。
TStringList を使うときにはよく以下のようにするので
SLit := TStringList.Create;
try
finally
SList.Free;
end;
こっちのほうが私にはなじみやすいのですけど
> プロジェクト部では initialization や finalization を使うほうが一般的なのでしょうか?
そのアプリが実行中、はじめから終わりまでずっと使いたい場合は initialization や finalization でやるべきです。
SLit := TStringList.Create;
try
finally
SList.Free;
end;
こういうのは、一時的に使ってすぐ廃棄っていうときの定型ですね
勉強になりました。
みなさんどうもありがとうございました。
> プロジェクト部では initialization や finalization を使うほうが一般的なのでしょうか?
自分は、あまりそういう使い方しません。
大概、メインフォームでインスタンスの生成・破棄を書いてしまいます。
あまり所有者不明の存在は作りたくない、というのが理由です。
> あまり所有者不明の存在は作りたくない、というのが理由です。
TObject からの派生クラスの所有者って意味不明。
anoneさん、
>あと TComponent 派生クラス以外で Owner を設定してはいけません。
これはどうしてでしょうか?
私は、TObjectから派生させた自前のクラスを作成し、例えばTForm等で
Hoge := THoge.Create(Self);
の形でインスタンスを生成し、Hoge側からTFormに何らかの通知を行う際、
このSelfを使用しているのですが。
Owner によるインスタンスの自動管理は TComponent からの派生クラス以外は
機能しません。
TObject から派生したクラスのコンストラクタに Owner を設定しても、普通の
意味での Owner としての機能は果たしません。自分で private に FOwner とか
して、使う分には勝手ですけど。
anoneさん、回答ありがとうございます。
>Owner によるインスタンスの自動管理は TComponent からの派生クラス以外は
>機能しません。
そういう意味でしたら、了解です。