[教程]怎么判断一个当前类的某个函数是否是纯虚函数

在 Delphi 中,所有纯虚函数的代码都指向了 System._AbstractError,我们可以通过它在基类中判定它是否子类是否实现了某个接口。不过遗憾的是,Delphi 中,_AbstractError 的地址,我们并不能直接用 @System._AbstractError 来获取地址,所以我们需要一点小技巧。

type
  TAbstractHelper=class
  protected
  class var
    FAbstractCode:Pointer;
    procedure AbstractMethod;virtual;abstract;
  public
    class constructor Create;
    class function IsAbstract<T>(AEvent:T):Boolean;static;
  end;

{ TAbstractHelper }
class constructor TAbstractHelper.Create;
type
  TMethodEvent=procedure of object;
var
  AProc:TMethod;
  AEvent:TMethodEvent absolute AProc;
begin
  with TAbstractHelper.Create do
  begin
    AEvent:=AbstractMethod;
    FAbstractCode:=aProc.Code;
    Free;
  end;
end;

class function TAbstractHelper.IsAbstract<T>(AEvent: T): Boolean;
var
  AMethod:TMethod absolute AEvent;
begin
  Result:=AMethod.Code=FAbstractCode;
end;

现在我们通过 TAbstractHelper.FAbstractCode 就取到了 System._AbstractError 的地址。

接下来就是如何实现判断:

TForm1=class(TForm)
...
protected
    procedure InternalLoadData;virtual;abstract;
...
public
    function SupportAutoload:Boolean;
end;

function TForm1.SupportAutoload: Boolean;
type
  TInternalLoadDataEvent = procedure of object;
begin
  Result:=TAbstractHelper.IsAbstract<TInternalLoadDataEvent>(InternalLoadData);
end;

上面的代码,TForm1 本身 InternalLoaData 是纯虚函数,SupportAutoload 会返回 false,而如果子类实现了 InternalLoadData 结果 SupportAutoload 就会返回 true,这样不用额外声明变量或子类重载函数,就可以实现完美的判定。

滚动至顶部