Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/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 在“中使用继承”;创建;TObject的构造函数_Delphi - Fatal编程技术网

Delphi 在“中使用继承”;创建;TObject的构造函数

Delphi 在“中使用继承”;创建;TObject的构造函数,delphi,Delphi,我应该在从TObject或TPersistent派生的类的构造函数中调用“inherited”吗 constructor TMyObject.Create; begin inherited Create; // Delphi doc: Do not create instances of TPersistent. Use TPersistent as a base class when declaring objects that are not components, but that

我应该在从TObject或TPersistent派生的类的构造函数中调用“inherited”吗

constructor TMyObject.Create;
begin
 inherited Create;   // Delphi doc: Do not create instances of TPersistent. Use TPersistent as a base class when declaring objects that are not components, but that need to be saved to a stream or have their properties assigned to other objects.    
 VectorNames := TStringList.Create;
 Clear;
end;

对。它什么也不做,没错,但它是无害的。我认为,始终调用继承的构造函数,而不检查是否存在实现,保持一致性是有价值的。有人会说,调用继承的Create是值得的,因为Embarcadero可能会在将来为TObject.Create添加一个实现,但我怀疑这是真的;它将破坏不调用继承的Create的现有代码。尽管如此,我认为仅出于一致性的考虑,称之为“一致性”是个好主意。

我总是这样做

如果要重构代码并将其移动到公共祖先,则调用继承的Create具有以下优点:

  • 如果公共祖先有一个构造函数,您不能忘记调用它
  • 如果公共祖先有一个具有不同参数的构造函数,编译器会就此发出警告
  • 您还可以覆盖“过程后构造”。无论是哪种构造函数,始终调用此过程

    public
      procedure AfterConstruction; override;
    end;
    
    procedure TfrmListBase.AfterConstruction;
    begin
      inherited;
      //your stuff, always initialized, no matter what kind of constructor!
    end;
    

    例如:如果您想创建一个与普通TObject.create不同的构造函数的对象,例如TComponent.create(AOwner)或自定义(重载)构造函数,您可能会遇到问题,因为您的覆盖没有被调用,并且(在本例中)您的“VectorNames”变量将为零。

    ,除非我需要一个非常优化的构造函数

    虽然Craig是对的,但这也是我将继承式创建称为继承式创建的主要原因,而不仅仅是一致性。“它什么都不做”??!!它启动基本的对象存储!并且可以执行在继承的基类中定义的必需操作。不调用它可能会导致最糟糕的错误和bug:那些您无法立即了解发生了什么的错误和bug。IIRC,在调用构造函数(Create)之前,基本存储已经分配好了。mj2008,您是对的。斯蒂金,你错了。阅读源代码!我认为最重要的原因是Gamecat声明的一个原因-在某些时候,您可能希望将您的类从TObject重新分配到其他对象,并且新类可能包含非平凡的构造函数。@Stijn,TObject的构造函数不做任何事情,分配存储由NewInstance完成,由InitInstance初始化。ToObject的两个类方法。如果未调用重写的构造函数,则它是子类中的错误。这是后代类开发人员需要担心的问题,而不是您。并且可以跳过对AfterConstruction的调用,原因与您可以跳过对构造函数的调用相同:子体提供自己的实现,而忽略调用继承的方法。Rob:如果您创建一个生成ToObject子体的工厂类,则不能使用ToObject.Create(),因为它不是虚拟的!如果您在工厂中生成一个TComponent子代:它有一个不同的构造函数(Create(AOwner))。这就是为什么您应该使用AfterConstruction:它总是被调用的,不管是什么类型的构造函数
    public
      procedure AfterConstruction; override;
    end;
    
    procedure TfrmListBase.AfterConstruction;
    begin
      inherited;
      //your stuff, always initialized, no matter what kind of constructor!
    end;