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

Delphi: Все константы постоянны, но некоторые из них более постоянные, чем другие?

Рассмотрим:

const 
   clHotlight: TColor = $00FF9933;
   clLink = clHotLight; //alias of clHotlight

[Error] file.pas: Constant expression expected

и альтернативная формулировка, которая работает:

const 
   clHotlight = TColor($00FF9933);
   clLink = clHotLight; //alias of clHotlight

Поясните.


Тогда рассмотрим:

const 
   AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
   SuperuserGUID = AdministratorGUID; //alias of AdministratorGUID

[Error] file.pas: Constant expression expected

И исправить.

Изменить: добавлено ключевое слово const перед объявлениями; кто-то не верил, что они были const.

4b9b3361

Ответ 1

clHotlight: TColor = $00FF9933; не является константой, а типизированной константой (= статическая переменная), то есть компилятор резервирует слот в памяти для TColor, который сначала будет хранить значение $00FF9933 во время выполнения.
Поскольку это значение может быть изменено позже (с опцией Assignable Const ON), он не является реальной константой и не может быть принят компилятором в clLink = clHotLight;

clHotlight = TColor($00FF9933); строго совпадает с clHotlight = $00FF9933;
Это истинная константа, и компилятор заменит clHotlight на ее значение $00FF9933, где бы он ни появлялся в коде. И для clLink.

Прочитайте этот вопрос SO ( В Delphi 7, почему я могу назначить значение const?) и все хорошие ответы там...

EDIT: о TGUID...
Проблема в том, что запись AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; не является правильной.
Для вызова StringToGUID за сценой используется магия компилятора, что позволяет выразить GUID как строку, которая по своей природе не является. Это записи.

Итак, попытка AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}'; не будет работать. Это не GUID...

Обходным решением является наличие типизированных константных и переменных, указывающих на одну и ту же область памяти с помощью директивы absolute:

const
   AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
var
   SuperuserGUID: TGUID absolute AdministratorGUID; //alias of AdministratorGUID
   RootGUID: TGUID absolute AdministratorGUID;      //alias of AdministratorGUID

Ответ 2

Я пробовал этот код:

  const
    CAnswer1 = 42;
    CAnswer2 : Integer = 42;

  var
    LAnswer : Integer;

  begin
    LAnswer := CAnswer1;
    LAnswer := CAnswer2;
  end;

и здесь приведен код:

Project9.dpr.18: LAnswer := CAnswer1;
004101AC C7056C6E41002A00 mov [$00416e6c],$0000002a //<- assign a hard-coded "42" value
Project9.dpr.19: LAnswer := CAnswer2;
004101B6 A1701C4100       mov eax,[$00411c70] //<- fetch a variable content
004101BB A36C6E4100       mov [$00416e6c],eax //<- assign this content 

Вы правы: некоторые константы более постоянные, чем другие. Вторая константа фактически обрабатывается компилятором как переменная.

Ответ 3

clHotlight: TColor = $00FF9933; 
          ^

Объявляет clHotlight как "переменную" (ну, ok "назначаемая константа", если вы разрешили это в параметрах компилятора) с помощью :.

Как вы нашли, объявив:

clHotlight = TColor($00FF9933); 

Не выделяет clHotlight, пока он не будет указан позже.

То же самое относится к вашему GUID.

Ответ 4

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

То, что пока еще не показано, - это то, как обойти проблему (в большом числе случаев), хотя пара была мучительно близка к отказу от этой тайны...:)

В вашем конкретном случае вы можете обойти проблему, изменив "сглаживание" значения и типизированного объявления константы следующим образом:

const
  clLink = $00FF9933;
  clHotlight: TColor = clLink;

clLink теперь предоставляет вашу истинную константу, а clHotlight - типизированная константа с таким же значением, как clLink.

Для GUID можно использовать один и тот же метод, но вы должны иметь в виду нормальное постоянное выражение, используемое для инициализации типизированной константы GUID - оно не использует запись, а просто литеральную строку, поэтому:

const
  ID_CONSTANT = '{AA1C8AF2-C290-40AB-9CF5-2888A46E1660}';
  GUID_CONSTANT: TGUID = ID_CONSTANT;

ПРИМЕЧАНИЕ.. Такие константы GUID прекрасно используются во всех местах, где требуется TGUID, например. IsEqualGUID (tguid, GUID_CONSTANT) и т.д.

Ответ 6

Правая часть объявления константы должна быть "константным выражением", которое определяется как "константное выражение - это выражение, которое компилятор может оценить без выполнения программы, в которой он встречается". Вы можете найти весь принятый синтаксис для постоянного выражения в руководстве по языку. Обратите внимание, что в руководстве по языку явно указано, что "типизированные константы не могут встречаться в постоянных выражениях". - и почему ваши объявления терпят неудачу, оба clHotlight: TColor = $00FF9933; и AdministratorGUID: TGUID =...; являются типизированными константами. Кроме того, постоянное выражение не может включать вызовы функций, кроме тех, которые перечислены в руководстве по языку (т.е. Length(), SizeOf() и некоторые другие), которые компилятор может вычислить во время компиляции. Перепишите этот путь:

const
  AdminGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
  AdministratorGUID: TGUID = AdminGUID;
  SuperuserGUID: TGUID = AdminGUID;

И он будет работать.

Ответ 7

Добро пожаловать в эволюцию Delphi. в delphi 1 и 2 вы не можете назначить начальное значение константы глобальному var (ex: var xVar: Integer = 1). Единственный способ, которым вы можете это сделать, - использовать const xVar: Integer = 1) и некоторые, где в ваших кодах, вы можете при необходимости изменить его на что-нибудь. Пока они не избавятся от этой древней особенности, вы не можете использовать конструкцию const xVar: Integer как значение const.

Приветствия Фам