为什么Delphi编译器不会为重新定义的常量发出警告?

9

我的同事遇到了一个常量突然“改变值”的情况;
原来,它被重新声明了:

unit Unit1;

interface

const
   MyConstant = 1;

implementation

end.

--

unit Unit2;

interface

const
   MyConstant = 2;

implementation

end.

--

Uses Unit1, Unit2;
// Uses Unit2, Unit1;

procedure TFrmRedefineConstant.FormShow(Sender: TObject);
begin
   ShowMessage('MyConstant: ' + IntToStr(MyConstant));
end;

这显示2。如果您在Uses语句中交换单元顺序,则会显示1

好的,但是为什么Delphi编译器不警告重复的常量名称(那将非常有帮助)?
我能做些什么来启用警告吗(看起来似乎不行)。


4
它本来可以的,但现在不行了。我猜你应该在 EMB 论坛上问问为什么这没有引起警觉……同样适用于函数、类等。 - user497849
1
为什么?因为能够在不同的单元中声明具有相同名称的符号/类型,并将其放置在使用单元的范围内,比在原始声明符号/类型的单元中更接近,这也可以成为一个巨大的优势。例如,没有它就无法实现Interposer类。 - Marjan Venema
@MarjanVenema 确实如此,但有些人更喜欢收到关于这种情况的通知,而不是去寻找错误... - user497849
3
在保持事物尽可能小的范围内的原则上,这是一个很好的例子。 - Stefan Glienke
2
事实证明,它被重新声明了。严格来说,它被“隐藏”了。并没有重新声明。有两种不同的声明,其中一种被隐藏了。 - David Heffernan
显示剩余2条评论
1个回答

6
由于 Delphi 的文档作用域规则,若两个单元声明同名变量、常量、类型、过程或函数,则编译器会使用最后在 uses 语句中列出的那个单元中的标识符。此行为自 Turbo Pascal 4.0 引入单元以来一直存在,并且单元在 uses 子句中出现的顺序决定了它们的初始化顺序并影响了编译器查找标识符的方式。(要从其他单元访问标识符,必须添加限定符:UnitName.Identifier。)

2
因为这是自1987年以来记录的预期行为。为什么要警告一个已经预期和记录的行为呢?当局部变量隐藏外部作用域时,它应该发出警告吗?或者类方法隐藏了过程或函数?你会得到很多警告,它们将毫无用处。在Delphi中,单元声明顺序并不无关紧要。开发人员必须按正确顺序列出单元。 有时候人们应该阅读他们使用的语言的官方文档。Google或StackOverflow并不是最好的选择。 - Mad Hatter
1
几乎所有编译器的警告确实都是在警告有预期和记录下的行为。编译器警告可以进行控制,开关操作。使用单元的全局影响以及对命名空间的影响是Delphi的一个巨大弱点。警告是有价值的。但这并不是重点。问题问了一个你没有回答的问题。问题是“为什么”? - David Heffernan
1
好的,TForm.Close并不隐藏System.Close。是在TForm或派生类的方法中隐式使用了with Self才会隐藏。如果警告所有可能的隐藏,那么警告会很嘈杂。但更好的做法是警告实际的隐藏。因此,您必须从这样的方法中调用Close以查看警告。但无论如何,您似乎不愿意回答这个问题。为什么编译器设计者选择不包括这样的警告。请在您的答案中给出引用。 - David Heffernan
2
你已经回答了自己。所有这些警告都会很嘈杂。 - Mad Hatter
1
这就像问为什么警察不会拦下我,警告我车是蓝色的一样:这不是一个警告。 "Delphi编译器没有发出警告,因为没有需要警告的内容"。这就是问题的答案。 - Ian Boyd
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接