我最近在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