我正在编写一个带有一些虚拟/抽象程序的类,我希望这些程序可以被覆盖。但是它们也可能不被覆盖,这也没关系。问题是找出其中一个程序是否实际被覆盖了。如果它们没有被覆盖,我不应该尝试调用这些程序,而是需要改变一些不同的东西。如果我试图打电话给其中一个并且没有被覆盖,我会得到Abstract Error
。
有没有办法可以检测这些程序是否被覆盖?
以下是他们如何宣布的样本:
type
TMyClass = class(TObject)
protected
procedure VProc; virtual;
procedure VAProc; virtual; abstract;
end;
答案 0 :(得分:4)
你可以这样做。请注意,我删除了“抽象”。它可能适用于“抽象”,但我没有尝试过。
type
TMyClass = class(TObject)
protected
procedure VProc; virtual;
procedure VAProc; virtual; //abstract;
end;
function GetVAProcAddress(Instance: TMyClass): pointer;
var
p: procedure of object;
begin
p := Instance.VAProc;
result := TMethod(p).Code;
end;
//in one of the TMyClass methods you can now write:
if GetVAProcAddress(self) <> @TMyClass.VAProc then
答案 1 :(得分:4)
我认为这是错误的方法,它闻起来真的很糟糕..一些建议:
答案 2 :(得分:4)
可以覆盖或不覆盖的方法不是抽象方法,它只是虚拟。
抽象方法是没有基本实现的方法,并且后代必须 提供实现
。在您的情况下,只需将它们声明为虚拟,并为它们提供您的设计所要求的NO-OP(无操作)默认实现:
type
TMyBaseClass = class
protected
procedure SomeProc; virtual;
end;
procedure TMyBaseClass.SomeProc;
begin
// NO-OP
end;
注意 - 这说明了我自己的记录故意NO-OP的个人约定,而不仅仅是留下一个空的实现。
你试图检测一个声明的抽象方法是否被覆盖的任何shennanigans,并且在此测试的基础上调用它 - 或者不调用它可能比简单地调用NO-OP实现花费更多的时间。另外,如果您需要在该基类中引入实现,则不必将该方法从抽象更改为非抽象(可能会破坏您使用该方法的那些“检测”电路,并且肯定会将其成本视为无关但纯粹的开销)。
答案 3 :(得分:1)
使用RTTI获取问题中类的相关虚拟方法的方法地址。将它与基类的相同方法的方法地址进行比较。如果它不相同,那么该方法被覆盖。
答案 4 :(得分:1)
如果你有这样的行代码:
lObj := TMyClass.Create;
您会注意到编译器将输出一条警告,说明您正在构建包含抽象方法TMyClass.VAProc的'TMyClass'实例。