Michael
Я получил ваш вопрос, но так как ваш исходный код не компилируется, я думаю, вы упустили смысл вашего вопроса; -)
Мой ответ немного сложнее того, что Мейсон пытался объяснить в своем втором ответе.
Проблема в том, что ваш вопрос подразумевает, что у вас есть «ссылка на класс» (например, 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.
Чтобы вернуться к исходному вопросу:
Когда ваша ссылка на класс ссылается на базовый класс, имеющий виртуальный конструктор, вы уверены, что вы всегда будете вызывать виртуальный конструктор, используя косвенное указание.
Когда ваша ссылка на класс ссылается на базовый класс, имеющий не виртуальный конструктор, вы уверены, что вы всегда будете вызывать не виртуальный конструктор, используя прямой вызов.
Надеюсь, это прояснит ваш вопрос.
- Йерун