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);' 因为它没有用覆盖指令标记。但是,该方法不能标记为覆盖:基类中不存在具有该签名的方法,并且将覆盖指令添加到该方法会导致编译器错误:

[DCC 错误].... E2037 'aMethod' 的声明与之前的声明不同。

这很明显,因为 TBaseClass 中不存在具有该签名的方法。

基类中仅存在“aMethod(const s:string)”,并且该方法被标记为“覆盖” -因此基类中没有任何内容被隐藏。

为什么这不是一个错误的警告?(也不是我遇到的第一个......)

IMO,对另一个问题的引用不正确。我有一个解决方案 -我只是使用了重构,并重命名了有问题的方法。但我不是在寻找解决方案,这是微不足道的。我正在寻找这个警告的解释。这个设计有问题吗?(也许同时使用重载和覆盖并不是好的设计——我同意这一点,但这并不是编译器警告的真正含义。)

4

1 回答 1

3

我最近在 Indy 遇到了同样的问题。它的TIdStack基类具有抽象GetSocketOption()SetSocketOption()方法,这些方法TIdStackBDSBase将覆盖和重载其自己的抽象方法,以供其后代(TIdStackWindows等)覆盖。我得到了这些完全相同类型的编译器错误。

例如:

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

事实证明,在某些情况下(如 Indy 的),编译器需要将基类方法声明为overload(即使基类本身没有相应的重载方法),以便派生类覆盖 + 重载它。

但是,当我这样做时,它在 XE2 及更早版本中不起作用,导致“隐藏虚拟方法”警告和其他错误。这似乎已在 XE3 中修复。所以我最终不得不在印地做的是:

  1. 将基本TIdStack方法声明为overload; virtual; abstract;.

  2. 在 中TIdStackBDSBase,将覆盖的方法声明为overload; override;,然后:

    一个。在 XE2 及更早版本中,将重载方法声明为reintroduce; overload;,并将后代的单独非重载virtual; abstract;方法声明为override.

    湾。在 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 回答