Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 重写和非重写构造函数_Delphi_Oop - Fatal编程技术网

Delphi 重写和非重写构造函数

Delphi 重写和非重写构造函数,delphi,oop,Delphi,Oop,我只想问一个简单的问题——我有一个从TLabel派生的类,如下所示: TMyLabel = class (TLabel) ... constructor Create(AOwner: TComponent); override; end; constructor TMyLabel.Create(AOwner: TComponent); begin inherited Create(AOwner); { some code } end; 现在,Delphi允许我编译有覆盖和没

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

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

constructor TMyLabel.Create(AOwner: TComponent); 
begin
  inherited Create(AOwner);
  { some code }
end;
现在,Delphi允许我编译有覆盖和没有覆盖的两个版本。你能解释一下区别是什么吗?除了在被重写时无法在
Create()
中请求我自己的参数之外。谢谢


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

好吧,如果我正确地记得Delphi(那是很久以前的事了,尽管当时是很好的时机:))当重写构造函数时,您可以通过类引用调用它(参见示例)

虚拟构造函数允许对象的多态实例化。这方面的经典示例是Delphi的.dfm流机制

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

t组件
的构造函数声明如下:

constructor Create(AOwner: TComponent); virtual;
var
  ComponentClass: TComponentClass;
  Component, Owner: TComponent;
....
ComponentClass = FindComponentClass(ReadComponentClassName);
Component := ComponentClass.Create(Owner);
对于要参与此机制的组件,它必须使用
override
指令声明其构造函数

流程的另一个关键是类引用。比如说

type
  TComponentClass = class of TComponent;
读取.dfm文件时创建组件的代码大致如下所示:

constructor Create(AOwner: TComponent); virtual;
var
  ComponentClass: TComponentClass;
  Component, Owner: TComponent;
....
ComponentClass = FindComponentClass(ReadComponentClassName);
Component := ComponentClass.Create(Owner);
现在,如果该机制没有使用虚拟构造函数,那么将调用的构造函数将是
TComponent.Create
。所以你的构造函数,
TMyLabel.Create
永远不会被调用


这就是为什么在从
TComponent

派生时必须在构造函数中包含override指令的原因。如果没有,编译器的可能副本会给您一个警告,对吗?从链接复制;“如果您不这样做,编译器可能会警告您TMinMatrix的构造函数正在“隐藏”TMatrix的构造函数。”--我还没有遇到隐藏组件构造函数的实际需要,尤其是TCOmponent似乎依赖于构造函数和析构函数的正确虚拟行为,所以一般来说,对于TCOmponent,这实际上接近于一个错误。是的,是的。它可能是在“隐藏”它,因为它不是直接的后代,但既然我用继承的
调用它,它有什么区别吗?好吧,它在构造函数内部对你没有任何区别,但是如果有人去将TMyLabel子类化,你故意破坏继承链接,对吗?我的猜测是,在某些实际情况下,您可能希望这样做,但不希望使用TComponents。另外,您可以看看正确的、被重写的虚拟构造函数可能会被类工厂调用,这些类工厂只知道构造函数第一次声明的基类。谢谢。但是,如果我想允许进一步派生
TMyLabel
,并且我想在创建时指定更多参数,那么这可能吗?@MartinMelka不,如果要让.dfm机制实例化标签,这是不可能的。它总是使用单个参数调用虚拟构造函数。您可能只需要使用该构造函数并添加一个方法或属性,以允许在创建后提供额外的参数。