3

次のようなコードがあります。

TBaseClass = class(TObject)
protected
  procedure aMethod(const s:string);virtual;abstract;
end;

TDerivedClass = class(TBaseClass)
protected
   procedure aMethod(const s:string);overload;override;
   procedure aMethod(const s:string;const x:integer);overload;
end;

コンパイラは次の警告を生成します。

[DCC 警告].... W1010 メソッド 'aMethod' は、基本型 'TBaseClass' の仮想メソッドを非表示にします

警告をクリックすると、「aMethod(const s:string;const x:integer);」が表示されます。override ディレクティブでマークされていないためです。ただし、そのメソッドをオーバーライドとマークすることはできません。そのシグネチャを持つメソッドは基本クラスに存在せず、オーバーライド ディレクティブをそのメソッドに追加すると、コンパイラ エラーが発生します。

[DCC エラー].... E2037 'aMethod' の宣言が前の宣言と異なります。

TBaseClass にはそのシグネチャを持つメソッドが存在しないため、これは明らかです。

基本クラスには「aMethod(const s:string)」のみが存在し、そのメソッドは「オーバーライド」とマークされているため、基本クラスの何も隠されていません。

これが誤った警告ではないのはなぜですか? (私が最初に出会ったものでもありません...)

他の質問への参照は正しくありません、IMO。私には解決策があります -私は単純にリファクタリングを使用し、問題のあるメソッドの名前を変更しました。しかし、私は簡単な解決策を探しているわけではありません。この警告の説明を探しています。このデザインに何か問題がありますか?(おそらく、オーバーロードとオーバーライドを一緒に使用するのは良い設計ではありません。それには同意できますが、それはコンパイラの警告の実際の内容ではありません。)

4

1 に答える 1

3

最近、インディで同じ問題に遭遇しました。そのTIdStack基本クラスには、その子孫 (など) がオーバーライドする独自の抽象メソッドでオーバーライドおよびオーバーロードする抽象メソッドとメソッドがありGetSocketOption()ますSetSocketOption()。これらのまったく同じ種類のコンパイラ エラーが発生していました。TIdStackBDSBaseTIdStackWindows

例えば:

type
  TIdStack = class(TObject)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle;
      ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption;
      out AOptVal: Integer); virtual; abstract;
    ...
  end;

.

type
  TIdStackBSDBase = class(TIdStack)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel;
      AOptName: TIdSocketOption; out AOptVal: Integer); overload; override;
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel;
      AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); overload; virtual; abstract;
    ...
  end;

procedure TIdStackBSDBase.GetSocketOption(ASocket: TIdStackSocketHandle;
  ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer);
var
  LBuf, LLen: Integer;
begin
  LLen := SizeOf(LBuf);
  GetSocketOption(ASocket, ALevel, AOptName, LBuf, LLen);
  AOptVal := LBuf;
end;

.

type
  TIdStackWindows = class(TIdStackBSDBase)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel;
      AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); override;
    ...
  end;

procedure TIdStackWindows.GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer);
begin
  ...
end;

TIdStack.GetSocketOption()が宣言されているかどうかに関係overloadなく、XE2 は次のエラーを報告します。

[DCC Error] IdStackWindows.pas(296): E2137 Method 'GetSocketOption' not found in base class

overload状況によっては (Indy のように) 、派生クラスがそれをオーバーライド + オーバーロードするために、コンパイラは (基本クラス自体に対応するオーバーロードされたメソッドがなくても) 基本クラスのメソッドを as として宣言する必要があることが判明しました。

ただし、それを行った場合、XE2 以前では機能せず、「仮想メソッドを非表示にします」という警告やその他のエラーが発生しました。これは XE3 で修正されたようです。だから私がインディでしなければならなかったことは次のとおりでした:

  1. TIdStack基本メソッドを として宣言しoverload; virtual; abstract;ます。

  2. TIdStackBDSBase、オーバーライドされたメソッドを として宣言し、次のようにしますoverload; override;

    a. XE2 以前では、オーバーロードされたメソッドを として宣言し、の子孫に対してreintroduce; overload;オーバーロードされていない別のメソッドを宣言します。virtual; abstract;override

    b. XE3 以降では、オーバーロードされたメソッドを として宣言し、overload; virtual; abstract;子孫overrideにそれらを正常にさせます。

つまり、次のコードは XE3 では機能しますが、XE2 では機能しません。

type
  TIdStack = class(TObject)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer); overload; virtual; abstract;
    ...
  end;

.

type
  TIdStackBSDBase = class(TIdStack)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer); overload; override;
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); overload; virtual; abstract;
    ...
  end;

  procedure TIdStackBSDBase.GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer);
  var
    LBuf, LLen: Integer;
  begin
    LLen := SizeOf(LBuf);
    GetSocketOption(ASocket, ALevel, AOptName, LBuf, LLen);
    AOptVal := LBuf;
  end;

.

type
  TIdStackWindows = class(TIdStackBSDBase)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); override;
    ...
  end;

  procedure TIdStackWindows.GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer);
  begin
    ...
  end;

ただし、次のコードは XE2 で機能します。

type
  TIdStack = class(TObject)
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer); overload; virtual; abstract;
    ...
  end;

.

type
  TIdStackBSDBase = class(TIdStack)
    ...
    procedure WSGetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); virtual; abstract;
    ...
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer); overload; override;
    procedure GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); reintroduce; overload;
    ...
  end;

procedure TIdStackBSDBase.GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; out AOptVal: Integer);
var
  LBuf, LLen: Integer;
begin
  LLen := SizeOf(LBuf);
  WSGetSocketOption(ASocket, ALevel, AOptName, LBuf, LLen);
  AOptVal := LBuf;
end;

procedure TIdStackBSDBase.GetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer);
begin
  WSGetSocketOption(ASocket, ALevel, AOptName, AOptVal, AOptLen);
end;

.

type
  TIdStackWindows = class(TIdStackBSDBase)
    ...
    procedure WSGetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer); override;
    ...
  end;

  procedure TIdStackWindows.WSGetSocketOption(ASocket: TIdStackSocketHandle; ALevel: TIdSocketOptionLevel; AOptName: TIdSocketOption; var AOptVal; var AOptLen: Integer);
  begin
    ...
  end;
于 2013-05-02T17:41:43.430 に答える