迈克尔,
我得到你的问题,但由于你的源代码没有编译,我认为你错过了你的问题的重点;-)
我的回答稍微详细说明了梅森在第二个回答中试图解释的内容。
手头的问题是您的问题暗示您有一个“类引用”(如 TClass 或 TComponentClass),它引用了具有虚拟构造函数的基类。但是,TClass 没有(TClass 引用具有非虚拟构造函数的类),但 TComponentClass 有。
使用类引用反汇编对构造函数的调用时,您会看到不同之处。通过类引用调用虚拟构造函数时,代码与调用非虚拟构造函数时的代码略有不同:
- 调用虚拟构造函数具有间接性
- 调用非虚拟构造函数进行直接调用
这个反汇编显示了我的意思:
TestingForVirtualConstructor.dpr.37: ComponentClassReference := TMyComponentClass;
00416EEC A1706D4100 mov eax,[$00416d70]
TestingForVirtualConstructor.dpr.38: Instance := ComponentClassReference.Create(nil); // virtual constructor
00416EF1 33C9 xor ecx,ecx
00416EF3 B201 mov dl,$01
00416EF5 FF502C call dword ptr [eax+$2c]
TestingForVirtualConstructor.dpr.39: Instance.Free;
00416EF8 E8CFCDFEFF call TObject.Free
TestingForVirtualConstructor.dpr.41: ClassReference := TMyClass;
00416EFD A1946E4100 mov eax,[$00416e94]
TestingForVirtualConstructor.dpr.42: Instance := ClassReference.Create(); // non-virtual constructor
00416F02 B201 mov dl,$01
00416F04 E893CDFEFF call TObject.Create
TestingForVirtualConstructor.dpr.43: Instance.Free;
00416F09 E8BECDFEFF call TObject.Free
因此,当您有一个构造函数是虚拟的类引用类型的变量,并且您通过该变量调用该构造函数时,您可以确定该变量中的实际类将具有一个虚拟构造函数。
您无法确定在哪个实际类上实现了该构造函数(好吧,不是没有额外的调试信息,例如来自 .DCU、.MAP、.JDBG 或其他来源)。
这是编译的示例代码:
program TestingForVirtualConstructor;
{$APPTYPE CONSOLE}
uses
Classes, SysUtils;
type
TMyComponentClass = class(TComponent)
MyStrings: TStrings;
constructor Create(Owner: TComponent); override;
end;
constructor TMyComponentClass.Create(Owner: TComponent);
begin
inherited;
end;
type
TMyClass = class(TObject)
MyStrings: TStrings;
constructor Create();
end;
constructor TMyClass.Create();
begin
inherited;
end;
procedure Test;
var
// TComponentClass has a virtual constructor
ComponentClassReference: TComponentClass;
ClassReference: TClass;
Instance: TObject;
begin
ComponentClassReference := TMyComponentClass;
Instance := ComponentClassReference.Create(nil); // virtual constructor
Instance.Free;
ClassReference := TMyClass;
Instance := ClassReference.Create(); // non-virtual constructor
Instance.Free;
end;
begin
try
Test;
except
on E: Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
回到你原来的问题:当你的类引用引用了一个具有虚拟构造函数的基类时,你确信你总是会使用间接调用一个虚拟构造函数。当您的类引用引用具有非虚拟构造函数的基类时,您肯定会始终使用直接调用来调用非虚拟构造函数。
希望这对您的问题有更多的了解。
——杰伦