Delphi 中公共和已发布的类成员有啥区别?

Posted

技术标签:

【中文标题】Delphi 中公共和已发布的类成员有啥区别?【英文标题】:What's the difference between public and published class members in Delphi?Delphi 中公共和已发布的类成员有什么区别? 【发布时间】:2011-03-10 14:46:53 【问题描述】:

请有人解释一下 Delphi 中公共和已发布的班级成员有什么区别?

我尝试查看 Delphi 帮助,我了解这些成员具有相同的可见性,但我不太了解它们有何不同以及何时应该使用已发布成员而不是公共成员。

非常感谢。

【问题讨论】:

【参考方案1】:

编译器为已发布成员生成 RTTI(运行时类型信息)元数据,但不为公共成员生成(默认情况下)。这样做的主要效果是对象的已发布属性将在设计时出现在 Object Inspector 中。

我不知道您是否正在编写组件,但如果您这样做,您可能知道属性和事件通常是发布的,因此可以使用 Object Inspector 进行设置。

公开

public
  property MyProperty: integer read FMyProperty write FMyProperty

MyProperty 将在对象检查器中可见。

已发布

published
  property MyProperty: integer read FMyProperty write FMyProperty

MyProperty 将在对象检查器中可见。

【讨论】:

虽然这是正确的,但它出现在对象检查器中的根本原因是已发布成员存在 RTTI 元数据。换句话说,您所看到的是潜在差异的一种影响。更正确的答案是发布成员有 RTTI,而公共成员没有。 @Lasse V. Karlsen:是的,你是对的。但由于这可能是最明显的区别(?),而且还没有其他答案指出,我现在不会删除我的答案。 抱歉,我说得不够清楚 :) 我同意,这是最明显的差异效果。我的意思是,您应该指出根本的区别是 RTTI,而不是删除您的答案(即使其他答案现在指向 RTTI。) 我认为值得指出的是,如果您询问有关公共方法和已发布方法之间差异的问题,那么 RTTI 一词对您来说可能也没有任何意义。 Andreas 提供了一个非常有用的答案。 但是方法不同。这个答案中没有提到它。至少有一个:“只能将一个构造函数声明为已发布 - 重载版本必须定义为公共。”从这里delphibasics.co.uk/RTL.asp?Name=Published 而且,发布的属性不能返回数组。【参考方案2】:

已发布的属性将导出运行时类型信息 (RTTI)。

看看here 了解 Delphi 中的 RTTI

【讨论】:

【参考方案3】:

运行时类型信息 (RTTI) 仅为 published 类成员生成。

【讨论】:

除非指定了 $M+ / $TYPEINFO ON,否则在这种情况下公共成员也会有 RTTI 如果这是真的,@Mjustin,那么这是对早期 Delphi 版本的更改。过去没有 $M+,public和published是等价的。也就是说,除非 $M+ 生效,否则已发布部分不会生成 RTTI。【参考方案4】:

如您所述,公共属性和已发布属性具有相同的可见性。发布的属性包含在 RTTI 中,公共属性不包含。

【讨论】:

RTTI 代表运行时类型信息或 Delphi 编译器在设计时需要的信息,以使对象检查器和 Delphi IDE 的其他部分在设计时正常工作。 为了完整性:Delphi 2010 也可以为公共成员生成 RTTI,实际上可以为所有成员生成 RTTI,包括受保护的和私有的。但发布的成员仍然是对象检查器“发布”并由自动流机制使用的成员。 Free Pascal 是否像 Delphi 2010 一样工作?如,它是否为公共财产生成 RTTI?为简单起见不使用发布是否安全?【参考方案5】:

在运行时,已发布部分和公共部分中的条目可同等访问

它们之间的主要区别在于组件的已发布项在设计时出现在对象检查器中。

发生这种情况是因为,对于已发布部分中的字段,RTTI 是自动生成的。

Object Inspector 选择它并使用它来识别要添加到其属性和事件列表中的内容。

【讨论】:

【参考方案6】:

附带说明,已发布还有一个特别之处:

类成员的默认可见性published,因此请检查以下不安全代码:

  TTopSecret = class(TObject)
    Name: string;
    Password: string;

    function DecryptPassword(const AValue): string;  
  public
    constructor Create(const AName, AEncryptedPassword: string);
  end; 

NamePasswordDecryptPassword() 在“全球”可见。

【讨论】:

【参考方案7】:

除了其他答案:

已发布的属性由流系统自动存储。

例如,如果您有一个 TComponent 的后代实例并使用 WriteComponent 将其写入 TStream,则所有 (好吧,不是全部,但这是另一个问题) 已发布的属性都将写入流中而没有任何进一步编码。

当然,流媒体系统只能这样做,因为 RTTI 可用于那些已发布的属性。

【讨论】:

这可能是最重要的区别! RTTI 只是实现这一目标所需的一些“粘合剂”。【参考方案8】:

似乎已经有很多好的答案,指出 Object INspector,RTTI, 等等。这些都是拼图的一部分。

如果去掉已发布的关键字,整个 Delphi RAD 工具设计将需要某种方式来指定哪些属性存储在 DFM 中,在组件属性检查器中检查,并且可以在运行时从 DFM 重新加载表单或创建数据模块。

总之,这就是 Published 的用途。令我感兴趣的是 QT 的设计者(最初是 TrollTech,后来成为诺基亚的一部分,后来仍然从 Digia 分拆出来)必须为他们的 C++ RAD 库“QT”模拟这种级别的 RTTI,添加一个“已发布”的等价物和一个“属性”等价物,而纯 C++ 仍然缺乏这种基本功能。

【讨论】:

以上是关于Delphi 中公共和已发布的类成员有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi的类和对象- 继承

本地 和 实例 变量之间有啥区别

哪个 Delphi 版本支持公共方法的 RTTI?

受保护和私有有啥区别? [复制]

c++里面的protect和public、private有啥区别?

Delphi 7:在 Win XP 或 Windows Server 2003 下编译有啥区别?