【问题标题】:Overridden and non-overridden constructor重写和非重写构造函数
【发布时间】:2012-03-06 00:53:12
【问题描述】:

我只是想问一个简单的问题 - 我有一个从 TLabel 派生的类,如下所示:

TMyLabel = class (TLabel)
  ...
  constructor Create(AOwner: TComponent); override;
end;

constructor TMyLabel.Create(AOwner: TComponent); 
begin
  inherited Create(AOwner);
  { some code }
end;

现在,Delphi 让我可以编译带有和不带有 覆盖 的两个版本。你能解释一下有什么区别吗?除了在覆盖时无法在Create() 中请求我自己的参数。谢谢

编辑:我的意思是 - virtual 和非虚拟基础后代构造函数之间有什么区别?我总是可以通过inherited Create()调用继承的构造函数,那有什么意义呢?

【问题讨论】:

  • 如果你不这样做,编译器会给你一个警告,对吧?来自链接的副本; “如果您不这样做,编译器可能会警告您 TMinMatrix 的构造函数正在“隐藏” TMatrix 的构造函数。” -- 我还没有遇到隐藏组件构造函数的实际需要,特别是 TCOmponent 似乎依赖于构造函数和析构函数的正确虚拟行为,所以一般来说,对于 TComponent,它实际上接近错误。跨度>
  • 是的,确实如此。它可能是“隐藏”它,因为它不是直接的后代,但既然我用inherited 调用它,它有什么区别吗?
  • 好吧,在构造函数内部对你没有任何影响,但是如果有人去继承 TMyLabel,你故意破坏了继承链,对吧?我的猜测是,在某些实际情况下你会想要,但不是 TComponents。

标签: delphi oop


【解决方案1】:

好吧,如果我没记错Delphi(那是前一阵子,虽然是个好时机:))当构造函数被覆盖时,您将能够通过类引用调用它(例如this spec)。

【讨论】:

  • 正确的、被覆盖的虚拟构造函数可能被类工厂调用,这些类工厂只知道第一次声明构造函数的基类。
【解决方案2】:

虚拟构造函数允许对象的多态实例化。典型的例子是 Delphi 的 .dfm 流机制。

读取 .dfm 文件和实例化表单的代码在编译时不知道要使用哪些类。该决定被推迟到运行时才能正确做出,即读取 .dfm 文件时。此外,您可以获得 .dfm 文件机制来创建不属于 VCL 的自定义组件,因此此 .dfm 机制必须能够正确实例化不属于 VCL 的类。

TComponent 的构造函数声明如下:

constructor Create(AOwner: TComponent); virtual;

对于参与此机制的组件,它必须使用 override 指令声明其构造函数。

该过程的另一个关键是类引用。例如

type
  TComponentClass = class of TComponent;

读取 .dfm 文件时创建组件的代码大致如下所示:

var
  ComponentClass: TComponentClass;
  Component, Owner: TComponent;
....
ComponentClass = FindComponentClass(ReadComponentClassName);
Component := ComponentClass.Create(Owner);

现在,如果该机制不使用虚拟构造函数,那么将调用的构造函数将是 TComponent.Create。所以你的构造函数 TMyLabel.Create 永远不会被调用。

这就是为什么在从TComponent 派生时必须在构造函数中包含覆盖指令的原因。

【讨论】:

  • 谢谢。但是,如果我想允许进一步推导 TMyLabel 并且我想在创建时指定更多参数,这可能吗?
  • @MartinMelka 不,如果您要让 .dfm 机制实例化您的标签,那是不可能的。它总是会使用单个参数调用虚拟构造函数。您可能应该只使用该构造函数并添加一个方法或属性以允许在创建后提供额外的参数。
猜你喜欢
  • 2015-03-24
  • 2017-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-25
  • 2020-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多