我最近在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中得到修复。所以,我最后不得不在印第安纳波利斯做的是:
申报基地TIdStack
方法为overload; virtual; abstract;
。
在TIdStackBDSBase
,声明重写的方法如overload; override;
,则:
一个。在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;
的可能重复的[Delphi的:方法“创建”隐藏基部的虚拟方法 - 但它在那里(http://stackoverflow.com/questions/9103263/delphi-method-create-hides-virtual-方法的基地,但它的权利在那里) – 2013-05-02 17:00:44
@J ...:这不是一个骗局。他接受了解决方案。我有一个解决方案 - 这不是我要找的。我正在寻找一个解释。 – Vector 2013-05-02 17:19:49
按照评论 - 我链接到最好的解决方案,可能是“为什么?”这个问题的最佳答案。在这里,但是(也在链接的标记dupe)http://stackoverflow.com/a/58167/327083 – 2013-05-02 17:26:56