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
;有人不相信他们是常量。
Consider:
const
clHotlight: TColor = $00FF9933;
clLink = clHotLight; //alias of clHotlight
[Error] file.pas: Constant expression expected
and the alternate wording that works:
const
clHotlight = TColor($00FF9933);
clLink = clHotLight; //alias of clHotlight
Explain.
Then consider:
const
AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
SuperuserGUID = AdministratorGUID; //alias of AdministratorGUID
[Error] file.pas: Constant expression expected
And fix.
Edit: Added keyword const
before declarations; someone didn't believe they were const.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
clHotlight: TColor = $00FF9933;
不是常量,而是类型常量(=静态变量),即编译器在内存中为 TColor 保留一个槽,该槽将保存值$00FF9933< /code> 最初在运行时。
由于该值稍后可以更改(使用“Assignable Const”选项打开),因此它不是真正的常量,并且不能被编译器在
clLink = clHotLight;
clHotlight = TColor($00FF9933 );
与clHotlight = $00FF9933;
严格相同
它是一个真正的常量,编译器将用其值
$00FF9933
替换它出现在代码中的任何位置。对于clLink
也是如此。阅读这个问题(在 Delphi 7 中,为什么我可以给 const 赋值?)以及那里所有好的答案...
编辑:关于 TGUID...
问题在于编写
AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
是不正确的。它使用一些编译器魔法在后台调用
StringToGUID
,从而可以方便地将GUID表示为字符串,而它们本质上不是字符串。它们是记录。因此,尝试
AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
将不起作用。这不是 GUID...解决方法是使用
absolute
让类型常量和变量指向同一内存区域> 指令:clHotlight: TColor = $00FF9933;
is not a constant but a typed constant (=static variable), i.e. the compiler reserves a slot in memory for a TColor which will hold the value$00FF9933
initially at run time.Because that value can be changed later (with the Assignable Const option ON), it is not a real constant and cannot be accepted by the compiler in
clLink = clHotLight;
clHotlight = TColor($00FF9933);
is strictly the same asclHotlight = $00FF9933;
It is a true constant and the compiler will replace
clHotlight
by its value$00FF9933
wherever it appears in the code. And forclLink
as well.Read on this SO question (In Delphi 7, why can I assign a value to a const?) and all the good answers there...
EDIT: about TGUID...
The problem is that writing
AdministratorGUID: TGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
is not proper.It is using some compiler magic to call
StringToGUID
behind the scene, allowing the convenience to express the GUID as a string which they are not by nature. They are records.So, trying
AdministratorGUID = '{DE44EEA0-6712-11D4-ADD4-0006295717DA}';
will not work. That is not a GUID...A workaround is to have a typed constant and variables pointing to the same memory area using the
absolute
directive:我尝试了这段代码:
这是生成的代码:
你是对的:有些常量比其他常量更恒定。
第二个常量实际上被编译器视为变量。
I tried this code :
and here is the produced code :
You are right : some constants are more constant than others.
The second constant is actually treated by the compiler as a variable.
通过
:< 将
clHotlight
声明为“变量”(好吧,如果您在编译器选项中允许这样做,那么可以是“可分配常量”) /代码>。正如您所发现的,声明:
不分配 clHotlight,直到稍后指定。
这同样适用于您的 GUID。
Is declaring
clHotlight
as a 'variable' (well, ok an 'assignable constant' if you've permitted this in compiler options) by means of the:
.As you've found, declaring:
Makes no allocation of
clHotlight
until it is specified later.The same applies to your GUID.
问题的出现是因为类型常量并不是真正的常量,正如其他人以不同程度的清晰度和成功解释的那样。
尚未展示的是如何解决这个问题(在很多情况下),尽管有几个人非常接近放弃这个秘密......:)
在你的具体情况下,你可以解决这个问题通过反转值和类型化常量声明的“别名”,如下所示:
clLink 现在提供真正的常量,clHotlight 是与 clHotlight 具有相同值的类型化常量强>clLink。
对于 GUID,可以使用相同的技术,但您必须记住用于初始化类型化 GUID 常量的正常常量表达式 - 它不使用记录,而是使用简单的文字字符串,因此:
注意:< /strong> 这样的 GUID 常量在所有需要 TGUID 的地方都可以完美使用,例如 IsEqualGUID( tguid, GUID_CONSTANT ) 等。
The problem arises because a typed constant is not, truly, a constant, as has been explained with varying degrees of clarity and success by others.
What hasn't as yet been shown is how to work around the problem (in a large number of cases), though a couple came tantalisingly close to giving up that secret... :)
In your specific case you can get around the problem by reversing the "aliasing" of the value and the typed constant declaration as follows:
clLink now provides your true constant and clHotlight is the typed constant that has the same value as clLink.
For the GUID's the same technique can be used, but you have to bear in mind the normal constant expression used to initialise a typed GUID constant - it doesn't use a record but a simple literal string, so:
NOTE: Such GUID constants are perfectly usable in all places where TGUID's are required, e.g. IsEqualGUID( tguid, GUID_CONSTANT ) etc.
请阅读此处了解 Delphi 中的类型常量
Read here Understanding Typed Constants in Delphi
常量声明的右侧必须是“常量表达式”,其定义为“常量表达式是编译器可以在不执行其出现的程序的情况下计算的表达式”。您可以在语言指南中找到常量表达式的完整可接受语法。
请注意,语言指南明确指出“类型化常量不能出现在常量表达式中”。 - 这就是为什么你的声明失败,两个 clHotlight: TColor = $00FF9933;和管理员GUID:TGUID = ...;是类型常量。
此外,常量表达式不能包含除语言指南中列出的函数调用(即编译器能够在编译时计算的 Length()、SizeOf() 和其他一些函数)之外的函数调用。
这样重写:
它会起作用。
The right side of a constant declaration must be a "constant expression", which is defined as "a constant expression is an expression that the compiler can evaluate without executing the program in which it occurs". You can find the whole accepted syntax for constant expression in the language guide.
Note that the language guide explicitly states "Typed constants cannot occur in constant expressions." - and that's why your declarations fails, both clHotlight: TColor = $00FF9933; and AdministratorGUID: TGUID =...; are typed constants.
Also, constant expression cannot include functions calls except those listed in the language guide (i.e. Length(), SizeOf(), and some others) that the compiler is able to compute at compile time.
Rewrite this way:
And it will work.
欢迎来到德尔福进化。在delphi 1 & 2、不能将初始常量值赋给全局var(例如:var xVar:Integer = 1)。您可以做到这一点的唯一方法是使用 const xVar: Integer = 1) 以及代码中的某些位置,然后您可以根据需要将其更改为其他内容。在他们摆脱这个古老的功能之前,您不能使用“const xVar:Integer”构造作为const值。
干杯
范
welcome to Delphi evolution. in delphi 1 & 2, you can not assign initial constant value to a global var (ex: var xVar: Integer = 1). The only way you can do that is using const xVar: Integer = 1) and some where in you codes, you can then change it to somethingelse if desired. Until they get rid of this ancient feature, you can not using "const xVar: Integer" construct as a const value.
Cheers
A Pham