Виртуальный конструктор Delphi

Я читал эту статью, потому что хотел чтобы понять полезность class of [ClassName], и я видел, что они объявляют виртуальный конструктор. Итак, я провел тест, который вы можете увидеть здесь:

введите описание изображения здесь

Я понимаю (из этой статьи), что виртуальные конструкторы полезны, когда я не знаю во время компиляции класс, который хочу построить, и могу использовать class of. В чем разница в коде, который я показал выше?

Если я объявил конструктор TFirst виртуальным без переопределения TSecond, я, конечно, получу предупреждение, и я могу удалить его, повторно введя или переопределив. Но разве конструктор не переопределяется автоматически (посмотрите на код слева)? Я считаю, что они равноценны.


person Raffaele Rossi    schedule 10.07.2017    source источник
comment
Пожалуйста, не используйте скриншоты для кода! Вы можете вставить выделенный синтаксисом код - используйте кнопку {} или посмотрите здесь.   -  person Uli Gerhardt    schedule 10.07.2017
comment
Они не эквивалентны. Вы заметите разницу, если попытаетесь создать экземпляр через ссылку на класс. Я почти уверен, что документация охватывает это. Имеет ли это?   -  person David Heffernan    schedule 10.07.2017
comment
Документация: docwiki.embarcadero.com/RADStudio/en/ docwiki.embarcadero.com/RADStudio/en/Class_References всегда разумно читать документацию   -  person David Heffernan    schedule 10.07.2017
comment
@RaffaeleRossi, как указал Дэвид, это в документе. Чтобы напрямую ответить на ваш вопрос, равны ли два кода или нет, это видно: при вызове через идентификатор типа класса конструктор, объявленный виртуальным, эквивалентен статическому конструктору. Однако в сочетании с типами ссылок на классы виртуальные конструкторы позволяют создавать полиморфные объекты.   -  person Alberto Miola    schedule 25.07.2017


Ответы (1)


Выполните этот код с обоими вариантами, и вы увидите разницу.

type
  TFirstClass = class of TFirst;

constructor TFirst.Create;
begin
  Writeln('TFirst.Create');
end;

constructor TSecond.Create;
begin
  Writeln('TSecond.Create');
end;

var
  firstClass: TFirstClass;
  first: TFirst;
begin
  firstClass := TSecond;
  first := firstClass.Create;
end.
person Stefan Glienke    schedule 10.07.2017
comment
Хорошо, спасибо, Стефан, но на самом деле мой вопрос был: есть ли разница, использую ли я vritual / override (в конструкторе отца / ребенка) или нет? В общем я имею ввиду - person Raffaele Rossi; 10.07.2017
comment
Я думаю, выполнение примера кода довольно четко показывает разницу - person Stefan Glienke; 10.07.2017
comment
Используйте код, показанный в этом ответе, как реализацию ваших заданных объявлений, @Raffaele. В невиртуальном случае вы увидите только сообщение о TFirst, тогда как в виртуальном случае вместо этого вы увидите сообщение о TSecond. (Но будьте осторожны: в обоих случаях проверка first is TSecond вернет True!) - person Rob Kennedy; 10.07.2017
comment
Хорошо, я думаю, что понял. В приведенном выше коде можно увидеть «TSecond.Create» с виртуальным / переопределением, потому что я собираюсь переопределить (фактически переопределив) конструктор. Без виртуального / переопределения я не даю новое определение TSecond.Create (на самом деле у меня НЕТ переопределения), поэтому я вижу TFirst.Create. Я думаю, что моя идея верна - person Raffaele Rossi; 10.07.2017
comment
@Raffaele: без виртуального конструктора используется конструктор, объявленный для типа (TFirstClass - ›class of TFirst). Но с виртуальным конструктором вы получаете конструктор фактического, а не объявленного класса, и фактический класс TSecond. То же самое, что и для виртуальных и невиртуальных нормальных методов. - person Rudy Velthuis; 10.07.2017
comment
Вместо того, чтобы говорить «выполнить это и увидеть разницу», вы могли бы опубликовать результат и объяснить разницу. - person spiderface; 07.06.2021