1

Delphiのコンストラクタに関する一連の質問のもう1つ。

仮想コンストラクターを持つ基本クラスがあります。

TComputer = class(TObject)
public
    constructor Create(Teapot: Integer); virtual;
end;

コンストラクターは、誰かが呼び出す必要があるときのために仮想です

var
   computerClass: class of TComputer;
   computer: TComputer;
begin     
   computer := computerClass.Create(nTeapot);

コンストラクターはoverridden子孫にあります:

TCellPhone = class(TComputer) 
public
   constructor Create(Teapot: Integer); override;
end;

TiPhone = class(TCellPhone ) 
public
   constructor Create(Teapot: Integer); override;
end;

WhereTCellPhoneTiPhone子孫はそれぞれ独自の初期化を行う機会があります(読みやすさのために含まれていないメンバーの)。

しかし今、私はオーバーロードされたコンストラクターをいくつかの祖先に追加します:

TCellPhone = class(TComputer) 
public
   constructor Create(Teapot: Integer); override; overload;
   constructor Create(Teapot: Integer; Handle: string); overload;
end;

TCellPhoneの代替コンストラクターは、他の仮想コンストラクターを呼び出すため、常に適切なオーバーライド動作を取得します。

constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
   TCellPhone.Create(Teapot); //call sibling virtual constructor

   FHandle := Handle;
end;

問題は、子孫のオーバーライドされたコンストラクターが呼び出されないことです。呼び出しの実際のスタックトレースチェーンは次のとおりです。

phone := TiPhone.Create(37, 'spout')
   constructor TCellPhone.Create(Teapot: Integer; Handle: string)
      constructor TCellPhone.Create(Teapot: Integer)
         constructor TComputer.Create(Teapot: Integer)
            TObject.Create

仮想であるへの兄弟呼び出しは、次TCellPhone.Create(int)の子孫のオーバーライドされたメソッドを呼び出す必要がありますTiPhone

phone := TiPhone.Create(37, 'spout')
   constructor TCellPhone.Create(Teapot: Integer; Handle: string)
      constructor TiPhone.Create(Teapot: Integer)
         constructor TCellPhone.Create(Teapot: Integer)
            constructor TComputer.Create(Teapot: Integer)
               TObject.Create

したがって、兄弟仮想コンストラクターを使用しようとすると、Delphiが期待どおりに機能しないようです。

では、あるコンストラクターが別のコンストラクターを使用するのは悪い考えですか?オーバーロードされたコンストラクターのコードが相互のコピーアンドペーストバージョンであるという設計意図はありますか?

.NETで、いくつかのコンストラクターが相互にチェーンしていることに気付きました。

public Bitmap(int width, int height) : this(width, height, PixelFormat.Format32bppArgb) {}

public Bitmap(int width, int height, PixelFormat format) {...}

これは、次の場合にのみ問題になるようです。

  • コンストラクターは仮想です
  • コンストラクターをオーバーロードします

あるコンストラクターに別のコンストラクターをオーバーロードさせることはできないというルールはありますか?

4

1 に答える 1

8

エラー..

constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
   TCellPhone.Create(Teapot); //call sibling virtual constructor

   FHandle := Handle;
end;

それは次のようになります。

constructor TCellPhone.Create(Teapot: Integer; Handle: string);
begin
   Create(Teapot); //call sibling virtual constructor

   FHandle := Handle;
end;

新しい TCellphone インスタンスを作成しただけで、他の Create メソッドを呼び出していません。

于 2010-10-08T16:23:03.973 に答える