Подтвердить что ты не робот

Способы записи и константные параметры в Delphi

Похоже, что компилятор Delphi не оценивает параметры записи const, когда "records-with-methods".

Не пытаясь раньше злоупотреблять конст-конвенцией, я был немного удивлен чтобы найти принятый код компилятора следующим образом:

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 f.i., компилятор будет правильно жаловаться, но вам разрешено вызывать методы, которые изменяют запись "const", даже без подсказки или предупреждения. Таким образом, это другое поведение, чем для ссылочных типов (таких как классы или динамические массивы), где допускаются прямые записи полей (поскольку const ограничивает только изменения самого параметра).

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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