Joh*_*ica 8 delphi virtual interface class
编译以下代码时出现错误:
TOmniParallelSimplePooledLoop = class(TOmniParallelSimpleLoop)
procedure Execute(loopBody: TOmniIteratorSimpleSimpleDelegate); overload; override;
Run Code Online (Sandbox Code Playgroud)
[dcc64 Error] OtlParallel.pas(846):E2170无法覆盖非虚方法
如果我将祖先方法设为虚拟,那么错误就会消失.
但是祖先方法声明在:
IOmniParallelSimpleLoop
...
procedure Execute(loopBody: TOmniIteratorSimpleSimpleDelegate); overload;
Run Code Online (Sandbox Code Playgroud)
基本方法TOmniParallelSimpleLoop从非虚拟到虚拟的重新声明是否会更改基类型,或者是已经虚拟的方法(由于它是接口方法的实现)?
换句话说:当接口方法从非虚拟变为虚拟时,编译器会输出不同的代码吗?
基本MSVC重新创建错误
program Project70;
{$APPTYPE CONSOLE}
uses
System.SysUtils;
type
I1 = interface
procedure DoSomething;
end;
T1 = class(TInterfacedObject, I1)
procedure DoSomething;
end;
T2 = class(T1)
procedure DoSomething; override;
end;
procedure T1.DoSomething;
begin
WriteLn('parent');
end;
procedure T2.DoSomething;
begin
Writeln('Child');
end;
begin
end.
Run Code Online (Sandbox Code Playgroud)
接口方法总是虚拟的吗?
接口的方法既不是虚拟的也不是非虚拟的.该概念不适用于接口方法.
另一方面,类的方法可以是虚拟的或非虚拟的.区别决定了方法调用的绑定方式.虚拟方法在运行时绑定,考虑到对象的运行时类型.并且使用对象引用的编译时类型在编译时绑定非虚方法.
编译器错误只是告诉您override这只对虚拟方法有意义.您的代码正在尝试使用override非虚拟方法.考虑一下这个程序,它根本不包含任何接口:
type
T1 = class
procedure DoSomething;
end;
T2 = class(T1)
procedure DoSomething; override;
end;
procedure T1.DoSomething;
begin
end;
procedure T2.DoSomething;
begin
end;
begin
end.
Run Code Online (Sandbox Code Playgroud)
此程序无法编译与您的程序完全相同的错误.该错误与接口无关.DoSomething在引入时声明为虚拟T1将解决错误.
基本方法
TOmniParallelSimpleLoop从非虚拟到虚拟的重新声明是否会改变基类型?
是的,它会的.它将该方法从非虚拟更改为虚拟.这意味着如上所述,方法调度以不同方式执行.这意味着类型的VMT会更改以适应新的虚拟方法.
或者该方法是否已经虚拟开始(由于它是接口方法的实现)?
使用方法实现接口的一部分这一事实并不会改变编译器处理它的方式.无论是否实现接口方法,都以相同的方式实现非虚方法.同样适用于虚拟方法.为实现接口而生成的VMT是一个独特的问题.
详细说明,每种方法都有一个地址.在调用非虚方法时,编译器确切地知道要调用哪个方法.因此它可以发出代码直接调用该已知方法.对于虚方法,编译器不知道将调用哪个方法.这由运行时类型决定.因此编译器发出代码来读取对象VMT中的已知条目,然后调用该方法.
现在,我相信您也知道,接口也是使用VMT实现的.但这并不意味着实现方法会自动升级为虚拟.界面只是一个VMT.当被认为是类的方法时,接口VMT引用的方法可以是虚拟的或非虚拟的.
type
ISomeInterface = interface
procedure Foo;
end;
TSomeObject = class(TInterfacedObject, ISomeInterface)
procedure Foo;
end;
....
var
Intf: ISomeInterface;
Obj: TSomeObject;
....
Intf := TSomeObject.Create;
Obj := Intf as TSomeObject;
// non-virtual method, direct dispatch at compile time
Obj.SomeMethod;
// interface method, dispatched via interface VMT
Intf.SomeMethod;
Run Code Online (Sandbox Code Playgroud)
因此,可以通过VMT调用方法的事实并不意味着必须以这种方式调用它.
| 归档时间: |
|
| 查看次数: |
438 次 |
| 最近记录: |