为什么即使我已将记录定义提供给所有单位,仍会收到"incompatible types"错误?



我正在写一个Delphi 2010应用程序。它有许多文件,其中两个名为Utils_ABS和Utils_MAT。我已经创建了一个两个文件都需要理解的记录类型,所以我把它放在它自己的文件中,名为TypeDefs.inc.

在Utils_MAT和Utils_ABS的顶部,我已经包括TypeDefs.inc.

unit Utils_ABS;
interface
{$WARNINGS ON}
{$HINTS ON}
{$WARN UNIT_PLATFORM OFF}
{$WARN SYMBOL_PLATFORM OFF}
uses
Windows, Messages, ... Utils, Analysis, UserFeedback, Utils_MAT;
{$I TypeDefs.inc}     // Include TypeDefs that are used multiple places
procedure ABS_Load;
...

Utils_MAT看起来非常相似,特别是与{$I TypeDefs.inc}相关。

关键项是两个文件都引用了第三个文件TypeDefs。. inc,作为一个INCLUDE,它有一个RECORD的定义:

type
TTableAttrType = Record
tabIOT: Boolean; // Is table an IOT
...
end;

在这个文件中除了这一个记录定义没有别的。

问题是当我编译时,我得到以下错误:

[DCC错误]Utils_ABS.pas(212): E2010不兼容的类型:'Utils_ABS. 'TTableAttrType'和'Utils_MAT '。TTableAttrType '

我完全糊涂了。如果它们来自相同的定义,它们怎么可能是不相容的类型呢?不是定义的副本,而是字面上相同的定义。

我检查了所有的源代码,这个TTableAttrType记录在其他任何地方都没有定义。

我试图注释掉$INCLUDE,并将记录的定义硬编码为Utils_ABS和Utils_MAT,但我仍然得到相同的错误。

如何让这个错误消失?我如何在一个地方定义一个记录结构,并有多个文件访问它?

通过包含这样的定义,您在两个单元中定义了类型。由于Pascal(以及扩展后的Delphi)使用指称类型系统,而不是结构类型系统,这两种类型是不一样的——它们有不同的名称,如错误消息所示。

将TTableAttrType的定义放在单独的单元中,并将该新单元放入另外两个单元的接口部分的uses子句中。然后该类型将只定义一次,并且您将不再有不兼容的类型。

尽管@Michael的解释是正确的,但还有一些重要的事情需要补充到这个答案中。

尽管{$INCLUDE ...}指令和Uses子句看起来很相似,但它们的工作原理却完全不同。{$INCLUDE}从指定单元导入源(即从指定单元读取然后粘贴到)到调用单元,而Uses子句编译指定单元,然后使用编译后的二进制文件(dcu)。因此,当您使用{$INCLUDE}时,实际上并不是共享相同的内容,而是复制它。它们的名称和结构相同并不重要,它们对编译器来说是完全不同的实体。另一方面,当使用编译对象时,您引用的是相同的共享实体。

最新更新