5

複合コントロールの汎用の祖先を構築しようとしています。最初のアイデアは次のようになりました。

type
  TCompositeControl<TControl1: TControl; TControl2: TControl> = class(TWinControl)
  private
    FControl1,
    FControl2: TControl;
  public
    constructor Create(AOwner: TComponent); override; 
  end;

  TLabelAndEdit = TCompositeControl<TLabel, TEdit>; // simple example for illustration only

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FControl1 := TControl1.Create(Self);
  FControl2 := TControl2.Create(Self);
end;

すでにご存知かもしれませんが、これによりコンパイラエラーE2568がトリガーされます。型パラメータ宣言にCONSTRUCTOR制約がないと新しいインスタンスを作成できません。ただし、制約を追加してconstructorも、パラメーターのないコンストラクターを意味するため、役に立ちません。

テンプレートをキャストしTControlてコードをコンパイル可能にします。

...
FControl1 := TControl(TControl1).Create(Self);
...

...ただし、実行時にアクセス違反が発生します。

おそらく機能するハックの1つは、RTTIを介してコンストラクターを呼び出すことですが、それはかなり汚い解決策だと思います。

基本的に機能するもう1つのハックは、クラス型変数を中間体として使用することです。

type
  TControlClass = class of TControl;

constructor TCompositeControl<TControl1,TControl2>.Create(AOwner: TComponent);
var
  lCtrlClass1,
  lCtrlClass2: TControlClass;
begin
  inherited Create(AOwner);
  lCtrlClass1 := TControl1;
  FControl1 := lCtrlClass1.Create(Self);
  lCtrlClass2 := TControl2;
  FControl2 := lCtrlClass2.Create(Self);
end;

よりクリーンな解決策はありますか?また、typeパラメーターで仮想コンストラクターを直接呼び出すのにclasstype-constraintでは不十分な理由を誰かが説明できますか?

4

4 に答える 4

6

あなたの型キャストは悪いです:TControl(TControl1).Create(Self)。これは、のインスタンスであることをコンパイラに通知しますTControl1が、インスタンスTControlはないことはわかっています。これはクラスリファレンスです。代わりに、クラス参照型に型キャストします。

FControl1 := TControlClass(TControl1).Create(Self);
于 2012-03-06T15:51:34.703 に答える
0

別の構文は

FControl1 := TControl1(TControl1.NewInstance); // get memory for object
FControl1.Create(self); // call type-specific constructor

FControl2 := TControl2(TControl2.NewInstance); // get memory for object
FControl2.Create(self); // call type-specific constructor

これはDelphiのClasses.pas::CreateComponentで使用されています。どのオプションが最も醜いのか判断できません!

于 2015-12-10T22:34:26.150 に答える
0

最新のデルファイバージョン(シアトル)のようですが、このコンパイラエラーはもう発生していません。私はアプリケーションと同じ問題を抱えていましたが、デルファイシアトルではなくDelphiXe8でコンパイルした場合のみでした

于 2016-02-14T17:07:11.453 に答える
-1

クラスがパラメーターなしのコンストラクター(TObjectなど)を使用している場合は、コンパイラーの指示に従って実行することをお勧めします。

「型パラメーター宣言にコンストラクター制約を追加する」

次のようになります。

TCompositeControl <Control1:TControl、コンストラクター; TControl2:TControl、コンストラクター> = Class(TWinControl)

そうすれば、ジェネリックTypeのコンストラクターに必要な呼び出しを行うことができるはずです。

とはいえ、パラメーターが必要なコンストラクターで動作するかどうかはわかりません。

うまくいったら教えてください。

于 2012-05-04T21:23:28.473 に答える