2

カスタム SDL GUI ツールキット (ソースはhttp://sourceforge.net/projects/lkgui/files/にあります) を作成しましたが、継承されたオブジェクトに問題があります。

オブジェクトがメイン プログラム内にある場合、コンストラクターが呼び出されないため、プログラムはオブジェクトを適切に初期化せず、いくつかのコマンドの後でクラッシュします (具体的には、TStartGameButton は GUI_Canvas から継承し、GUI_Element から継承し、GUI_Element で定義されていないものはすべてクラッシュします)。 EAccessViolation のあるプログラム)。オブジェクトがユニット内に配置されると、この問題はなくなります。

ユニットにそのままにしておくことができることは理解していますが、うまくいけば回避できるいくつかの醜いコードにつながるでしょう。

なぜこれが起こっているのか、どうすれば回避できるのか、誰にも分かりますか?

4

2 に答える 2

3

古いスタイルの Delphi オブジェクトは、Delphi 2 のリリース以降、おそらくそれ以前に壊れています。stringまたは動的配列などのコンパイラ管理型のフィールドがある場合、継承はうまくいきません。2004 年にcomp.lang.pascal.delphi.miscでそれについての議論がありました。これを再現するコードは次のとおりです。

type
  TBase = object
  public
    s: string;
  end;

  TDerived = object(TBase)
  end;

procedure test;
var
  obj: TDerived; //okay for TBase!
begin
  assert(obj.s = '', 'uninitialized dynamic variable');
end;

そして実際にTBaseは、関数のプロローグ コードがたまたま生成される方法のため、偶然にのみ問題ありません。その関数に追加のコードを入れると、とにかくクラッシュする可能性があります。

実際、これはまさにあなたが観察したとおりです — 古いスタイルのオブジェクトは適切に初期化されません。それらの文字列フィールドは、最初から空の文字列を保持していません。代わりに、それらはガベージを保持するため、 のようなものを使用せずにそれらを自分で初期化することさえできませんFillChar.

これは、変数がローカル変数であるためと思われます。ユニット スコープ (「グローバル」) 変数は問題なく動作するようです。ユニット スコープで宣言されているがユニットの初期化セクションでのみ使用される変数、またはプログラム スコープで DPR ファイルのメイン begin-end ブロックでのみ使用される変数は、コンパイラによってローカル変数として扱われるため、すべての変数には設定されません。 -bits-zero はグローバル版と同様です。変数宣言をユニットに移動しても、DPR ファイルで引き続き使用すると、「グローバル」ステータスに昇格します。

あなたのTGUI_Elementタイプには というstringメンバーがDbgNameあり、それがタイプ階層にある唯一の文字列フィールドのようです。それを削除するか、に変更するとShortString、少なくとも一時的にクラッシュがなくなるはずです。

于 2010-01-27T14:56:36.543 に答える
0

仮想にするのではなく、すべてのオブジェクトに個別の名前付きコンストラクターを与えるのはなぜですか?

  type   tx = object
                constructor init; virtual;
                end;
         txx = object(tx)
                   constructor init; virtual; // like override in Delphi classes.
                  end;

視覚的な階層を確認する必要がある場合は、Free Vision を参照してください。TP オブジェクト モデルのほぼすべての側面が示されています。

どうやら仮想コンストラクターは TP モデルでは使用できません。

于 2010-01-27T14:14:06.573 に答える