为什么我会得到“不兼容的类型”即使我已经为所有单位提供了记录定义,仍然会出现错误?
我正在编写一个 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 中,但我仍然遇到相同的错误。
我怎样才能消除这个错误? 如何在一个地方定义记录结构,并让多个文件访问它?
I am writing a Delphi 2010 application. It has many files, two of which are called Utils_ABS and Utils_MAT. I have created a record type that both files need to understand, so I put it in its own file, called TypeDefs.inc.
At the top of both Utils_MAT and Utils_ABS, I have INCLUDED 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 looks very similar, especially as relates to {$I TypeDefs.inc}
.
The key item is that both files reference a third file, TypeDefs.inc, as an INCLUDE, which has the definition of a RECORD:
type
TTableAttrType = Record
tabIOT: Boolean; // Is table an IOT
...
end;
There is nothing else but this one record definition in this file.
The problem is that when I compile, I get the following error:
[DCC Error] Utils_ABS.pas(212): E2010 Incompatible types: 'Utils_ABS.TTableAttrType' and 'Utils_MAT.TTableAttrType'
I am totally confused. How can they be incompatible types if they come from the same definition? Not a copy of the definition, but literally the same definition.
I have checked all my source code, and this TTableAttrType record is not defined anywhere else.
I have tried to comment out the $INCLUDE, and hard-code the definition of the record into both Utils_ABS and Utils_MAT, but I still get the same error.
How do I get this error to go away?
How do I define a record structure in one place, and have multiple files access it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过包含这样的定义,您可以在两个单位中定义类型。由于 Pascal(以及扩展的 Delphi)使用 主格类型系统,而不是 结构类型系统,这两种类型不相同 - 它们具有不同的名称,如错误所示 信息。
将 TTableAttrType 的定义放在一个单独的单元中,并将该新单元放入其他两个单元中接口部分的 use 子句中。那么该类型只会被定义一次,并且您将不再有不兼容的类型。
By including the definition like this, you are defining the type in both units. Since Pascal (and by extension Delphi) uses a nominative type system, rather than a structural type system, the two types are not the same - they have different names, as shown in the error message.
Put the definition of TTableAttrType in a separate unit, and throw that new unit into the uses clause of the interface section in the two other units. Then the type will only be defined once, and you will no longer have incompatible types.
尽管@Michael 的解释是正确的,但这个答案中还需要添加一些重要的内容。
尽管看起来相似
{$INCLUDE ...}
指令和Uses
子句的工作方式完全不同。{$INCLUDE}
将源代码(如读取然后粘贴到)从指定单元导入到调用方单元,而Uses
子句编译指定单元,然后使用编译后的二进制文件 (dcu)。因此,当您使用 {$INCLUDE} 时,您实际上并不是在共享相同的内容,而是在复制它。尽管它们的名称和结构相同,但它们对于编译器来说是完全不同的实体。另一方面,当使用编译对象时,您指的是完全相同的共享实体。Even though @Michael's explaination is true, there's some important thing to be added to this answer.
Even though look similar
{$INCLUDE ...}
directive andUses
clause work totally different.{$INCLUDE}
imports the source (as in, reads from and then pastes into) from the specified unit into the caller unit whereasUses
clause compiles the specified unit and then uses the compiled binary (dcu). So when you use {$INCLUDE}, you're not actually sharing the same thing but duplicating it instead. Doesn't matter their names and structures are same, they're totally different entities to the compiler. When using a compiled object on the other hand, you're referring to the very same shared entity.