Почему конструкторы без параметров не допускаются к записям?

Следующее объявление:

type
  TRec = record
    constructor Create;
  end;

создает эту ошибку компиляции:

E2394 Параметрические конструкторы, недопустимые для типов записей

документация довольно бесполезно заявляет:

Дополнительная информация для этой ошибки или предупреждения отсутствует.

Мой вопрос в том, почему язык был разработан таким образом. Было ли это сделано так: эхо аналогичное ограничение для С# structs?

руководство по языку говорит следующее:

Записи создаются автоматически, используя конструктор no-argument по умолчанию, но классы должны быть явно построены. Поскольку записи имеют конструктор без аргументов по умолчанию, любой пользовательский конструктор записи должен иметь один или несколько параметров.

Но это не имеет большого смысла. Если для записи есть конструктор по умолчанию, он не может быть найден через RTTI. И даже если бы это было так, почему это означало бы невозможность добавить еще один? Вы можете сделать это для занятий.

Возможно, обоснование состоит в том, что если бы нам разрешили определять наши собственные конструкторы без параметров, мы бы ожидали, что компилятор их вызовет автоматически.

Примечание. Я понимаю, что вы можете использовать безпараметрическую статическую функцию класса в качестве обходного пути. В самом деле, я лично всегда предпочитаю использовать статическую функцию класса вместо конструкторов записи. Но это не вопрос. Я действительно хочу знать, почему конструкторы без параметров не допускаются к типам записей.

Ответ 1

Я не могу дать вам окончательный ответ (только разработчики компилятора могут), но я подозреваю, что это не связано с прошлым Delphi.NET, а скорее с отношением Delphi с С++ Builder.

Как cppreference говорит:

Конструктор по умолчанию - это конструктор, который может быть вызван без аргументов (либо с пустым списком параметров, либо с аргументами по умолчанию для каждого параметра).

С++ допускает конструкторы без параметров, и эти конструкторы без параметров станут стандартным конструктором в С++. Конструктор по умолчанию вызывается во многих ситуациях, например. если вы просто объявите:

Foo myFoo;

Вызывается конструктор по умолчанию. Это не происходит в Delphi, но программист на С++ может это ожидать. Аналогичным образом, если вы выполните:

Foo elements[1000];

Конструктор по умолчанию вызывается для каждого элемента (я проверил это). Это также не происходит в Delphi, хотя программист на С++ может это ожидать.

Другие подсказки, что это связано с С++:

  • Конструкторы с разными именами (например, Init) также не допускаются. Это, похоже, указывает на конфликты с С++ или с С#, так как в обоих конструкторах есть имя класса или структуры, поэтому любой конструктор без параметров будет сопоставлен с Foo() (в структуре или классе под названием Foo.)
  • Конструкторы с только параметрами по умолчанию также не допускаются. Это соответствует описанию cppreference для конструкторов по умолчанию с только аргументами по умолчанию.

В целом, есть подсказки, что конструкторы без параметров (или те, которые имеют только параметры по умолчанию) конфликтуют с С++ (т.е. С++ Builder), и поэтому они не разрешены.

Обратите внимание, что это не единственное ограничение, вызванное различиями с С++: например. в Delphi вы также не можете вводить целые числа в и из типов с плавающей точкой, потому что в C и С++ это приведет к преобразованию, а в Delphi - просто приведет к переинтерпретации бит. Чтобы не путать людей, которые приходили в Delphi с C или С++, ограничение на литье было размещено на типах с плавающей точкой. Может быть больше.