8

クラス階層があります。これは次のとおりです。

type
TMatrix = class
    protected
      //...
    public
      constructor Create(Rows, Cols: Byte);
    //...
type
  TMinMatrix = class(TMatrix)
    private
      procedure Allocate;
      procedure DeAllocate;
    public
      constructor Create(Rows, Cols: Byte);
      constructor CreateCopy(var that: TMinMatrix);
      destructor Destroy;
  end;

ご覧のとおり、派生クラスのコンストラクターと基底クラスのコンストラクターは同じパラメーター リストを持ちます。派生コンストラクターから基本クラス コンストラクターを明示的に呼び出します。

constructor TMinMatrix.Create(Rows, Cols: Byte);
begin
   inherited;
   //...
end;

Delphiで基本クラスのコンストラクタを明示的に呼び出す必要がありますか? 何をしようとしているのかを明確にするために、オーバーロードまたはオーバーライドを設定する必要があるのでしょうか? 私は C++ でそれを行う方法を知っています - 基本クラス コンストラクターを明示的に呼び出す必要があるのは、いくつかのパラメーターをそれに渡したい場合だけです - しかし、Delphi プログラミングの経験はあまりありません。

4

4 に答える 4

14

私の知る限り、ここには2つの別々の問題があります。

子クラスのコンストラクターが基本クラスのコンストラクターを呼び出すことを確認します

基本クラスのコンストラクターを明示的に呼び出す必要があります。

constructor TMinMatrix.Create(Rows, Cols: Byte);
begin
   inherited;
   //...
end;

子クラスのコンストラクターが基本クラスのコンストラクターをオーバーライドすることを確認する

また、子クラスのコンストラクターoverrideと基本クラスのコンストラクターvirtualを作成して、コンパイラーが2つの間の関係を認識できるようにする必要があります。そうしないと、コンパイラーは、TMinMatrixのコンストラクターがTMatrixのコンストラクターを「隠している」ことを警告する可能性があります。したがって、正しいコードは次のようになります。

type
TMatrix = class
    protected
      //...
    public
      constructor Create(Rows, Cols: Byte); virtual;    // <-- Added "virtual" here
      //...
type
  TMinMatrix = class(TMatrix)
    private
      //...
    public
      constructor Create(Rows, Cols: Byte); override;   // <-- Added "override" here
      constructor CreateCopy(var that: TMinMatrix);
      destructor Destroy; override;                     // <-- Also make the destructor "override"!
  end;

デストラクタも作成する必要があることに注意してくださいoverride

さまざまなパラメーターを持つコンストラクターの紹介

オーバーライドできるのは、同じパラメーターリストを持つコンストラクターのみであることに注意してください。子クラスに異なるパラメーターを持つコンストラクターが必要であり、基本クラスのコンストラクターが直接呼び出されないようにする場合は、次のように記述します。

type
TMyMatrix = class(TMatrix)
//...
public
  constructor Create(Rows, Cols, InitialValue: Byte); reintroduce; virtual;
//...
end

implementation

constructor TMyMatrix.Create(Rows, Cols, InitialValue: Byte);
begin
  inherited Create(Rows, Cols);   // <-- Explicitly give parameters here
  //...
end;

これが物事をより明確にすることを願っています...頑張ってください!

于 2008-12-11T20:04:23.610 に答える
3

オーバーロードは、メソッドが同じ名前でパラメーターが異なることをコンパイラーに通知します。

オーバーライド。メソッドが基本クラスで宣言された仮想または動的にオーバーライドすることをコンパイラーに通知します。

Reintroduceは、基本クラスで宣言された仮想メソッドまたは動的メソッドを非表示にします。

これらの定義は、レイ・リシュナーの著書{一言で言えばDelphi}からのものです。

type
  TFirst = class
  private
    FValue: string;
    FNumber: Integer;
  public
    constructor Create(AValue: string; ANumber: integer);

    property MyValue: string read FValue write FValue;
    property MyNumber: Integer read Fnumber write FNumber; 
  end;

  TSecond = class(TFirst)
  public
    constructor Create(AValue: string; ANumber: Integer);
  end;

constructor TFirst.Create(AValue: string; ANumber: integer);
begin
  MyValue := AValue;
  MyNumber := ANumber;
end;

{ TSecond }

constructor TSecond.Create(AValue: string; ANumber: Integer);
begin
  inherited;
end;

宣言されたTSecondは、TFirstの作成を呼び出しますが、継承されていない場合、TSecondメンバーは空のままになります。

于 2008-12-11T20:07:08.237 に答える
3

継承されたメソッドを明示的に呼び出す必要があります。Delphi はそれを行いません。これは仕様によるものです。たとえば、継承された動作を呼び出したくない場合など、仮想メソッドを使用する場合があるためです。

また、個人的な好みの問題として、継承された呼び出しを完全に書き出すのが好きです。(継承されたCreate(Rows, Cols); は単に継承されたのではなく;単純な理由の 1 つで、コードのトラバースがはるかに簡単になります。メソッド呼び出しが書き出されている場合は、それをコントロールクリックして取得できます。元祖メソッドへ。

于 2008-12-12T18:42:08.680 に答える
2

同じ名前のコンストラクターは両方ともオーバーロードする必要があります。

type
  TMatrix = class
  protected
    //...
  public
    constructor Create(Rows, Cols: Byte);
    //...
type
  TMinMatrix = class(TMatrix)
  public
    constructor Create(Rows, Cols: Byte); overload;
    constructor Create(var that: TMinMatrix); overload;
  end;

継承されたコンストラクターを呼び出すことをお勧めします。

constructor TMinMatrix.Create(Rows, Cols: Byte);
begin
   inherited Create(Rows, Cols); // Need to call the full name if the parameters are changed.
   //...
end;
于 2008-12-11T20:02:34.940 に答える