Методы записи и константные параметры в Delphi - PullRequest
12 голосов
/ 14 сентября 2011

Похоже, что компилятор Delphi не учитывает const параметров записи, когда задействованы "записи с методами".

Не пытаясь злоупотребить const Соглашение ранее, я был немного удивлен, обнаружив, что компилятор принял такой код:

type
    TTest = record
       Field : String;
       procedure Update;
    end;

procedure TTest.Update;
begin
    Field := Field + '+1';
end;

procedure DoStuff(const t : TTest);
begin
    ShowMessage(t.Field);
    t.Update;
    ShowMessage(t.Field);
end;

Хотя, если вы попытаетесь сделать t.Field:='doh'; в DoStuff fi, компиляторПравильно жаловаться, но вы можете вызывать методы, которые изменяют запись «const», даже без подсказки или предупреждения.Так что это другое поведение, чем для ссылочных типов (таких как классы или динамические массивы), где прямая запись в поля разрешена (поскольку const ограничивает только изменения самого параметра).

Добавление :это позволяет модифицировать объявленные константы времени компиляции таким же образом, как в:

const
   cTest : TTest = (Field : '1');
...
cTest.Update;              // will show '1' then '1'+'1'
ShowMessage(cTest.Field);  // will show '1' (because optimized at compile-time)

Это допустимое / документированное поведение?или просто недостаток компилятора?

Ответы [ 2 ]

15 голосов
/ 14 сентября 2011

const никогда не накладывает никаких ограничений на вызовы методов в Delphi, будь то записи или экземпляры классов. Поэтому я не думаю, что есть что-то несовместимое с обработкой вызовов методов.

Если методы не могут быть вызваны для записи, переданной в качестве параметра const, то это в значительной степени сделает записи бесполезными. Это будет означать, например, что не может быть вызван получатель свойства. Чтобы наложить ограничения на такие записи, передаваемые как const, необходимо использовать эквивалентную концепцию для константных функций-членов C ++. Это позволило бы компилятору знать, что определенные методы не являются мутациями.

4 голосов
/ 14 сентября 2011

Дэвид довольно хорошо проанализировал ограничение. Если бы компилятор проверял такие детали, он мог бы сделать это с некоторым штрафом. Кроме того, я не вижу ничего плохого в поведении компилятора. Метод, который получает запись, не может напрямую изменять ее данные, но только при использовании метода, который она содержит. Запись в этом случае работает как объект: вы можете так же, как объект, как const, и при этом у вас есть та же проблема, которую вы описали, т.е. методы объекта могут использоваться для изменения его данных.

Преимущество объекта в том, что такие методы могут быть объявлены как частные, что позволяет вам защитить его данные. Вы могли бы даже создать унаследованный класс, который делает именно это, а именно, скрывая все возможности изменять свои данные. Может быть, вы хотите попробовать этот подход?

...