web-dev-qa-db-ja.com

Delphi / Pascal:別のプロトタイプでコンストラクターをオーバーロードする

TFormの子クラスを作成しようとしています

  1. 特定の場合のための特別なコンストラクター、および
  2. 現在のコードとの互換性を維持するデフォルトのコンストラクター。

これは私が今持っているコードです:

interface
  TfrmEndoscopistSearch = class(TForm)
  public
    /// original constructor kept for compatibility
    constructor Create(AOwner : TComponent); overload; override;
    /// additional constructor allows for a caller-defined base data set
    constructor Create(AOwner : TComponent; ADataSet : TDataSet; ACaption : string = ''); overload;
  end;

動作しているように見えますが、コンパイラの警告が常に表示されます。

 [警告] test.pas(44):メソッド 'Create'は、基本型 'TCustomForm' 
の仮想メソッドを非表示にします。
  • 「過負荷」を追加します。 2番目のコンストラクターがコンパイルされない後。 「[エラー] test.pas(44):「作成」の宣言が以前の宣言と異なります」。
  • 2番目のコンストラクターをクラス関数にすると、エラーや警告なしでコンパイルされますが、実行時にアクセス違反で終了します(すべてのメンバー変数はnilです)。
19

次のように、2番目のreintroduceの前にoverloadを追加してみてください。

  TfrmEndoscopistSearch = class(TForm)
  public
    /// original constructor kept for compatibility
    constructor Create(AOwner : TComponent); overload; override;
    /// additional constructor allows for a caller-defined base data set
    constructor Create(AOwner : TComponent; ADataSet : TDataSet; ACaption : string = ''); reintroduce; overload;
  end;

これはTurboDelphiでコンパイルされます。 publicメソッドのオーバーロードが制限されているため、コンパイルするにはpublishedが必要でした。

19
Uli Gerhardt

これを回避する本当に簡単な方法があります。 新しいコンストラクターに別の名前を付けます。他の一般的な言語とは異なり、Delphiには名前付きコンストラクターがあります。それらをCreateと呼ぶ必要はありません。新しいCreateWithDatasetを呼び出すことができ、仮想Createコンストラクターにまったく干渉しません。

TfrmEndoscopistSearch = class(TForm)
  /// original constructor kept for compatibility
  constructor Create(AOwner: TComponent); override;
  /// additional constructor allows for a caller-defined base data set
  constructor CreateWithDataset(AOwner: TComponent; ADataSet: TDataSet; ACaption: string = '');
end;

実際、このクラスを多態的にインスタンス化しない限り、元のコンストラクターも必要ありません。あなたはこのようにあなたの新しいものを宣言することができます:

TfrmEndoscopistSearch = class(TForm)
  /// additional constructor allows for a caller-defined base data set
  constructor Create(AOwner: TComponent; ADataSet: TDataSet; ACaption: string = ''); reintroduce;
end;

TfrmEndoscopistSearchで引数1つのコンストラクターを直接呼び出そうとすると、コンパイルエラーが発生します。


(多態的に作成するには、通常、Application.CreateFormを使用する必要があります。

Application.CreateForm(TfrmEndoscopistSearch, frmEndoscopistSearch);

これは常に、TComponentで導入された1引数の仮想コンストラクターを呼び出します。それがあなたのメインフォームでない限り、あなたはそれをする必要はありません。私は Application.CreateFormに対する私の気持ち について書いたことがあります。)

31
Rob Kennedy
constructor Create(AOwner:Tcomponent;str:string);overload;
... 
constructor TfrmEndoscopistSearch.Create(AOwner: Tcomponent; str: string);
    begin
    inherited Create(AOwner);
    showmessage(str);
    end;

これはトリックを行う必要があります

6
Radacina