【问题标题】:Can it make sense to call one overloaded constructor from another?从另一个调用一个重载的构造函数有意义吗?
【发布时间】:2014-01-30 16:17:07
【问题描述】:

如果我有两个重载的构造函数,一个没有参数,一个有参数:

constructor Create; overload;
constructor Create(Param: TObject); overload;

如果我想让第一个中的代码运行,那么在第二个中调用它是否有意义?并且继承先调用父构造函数?

constructor TMyType.Create(Param: TObject);
begin
  inherited Create;
  Create;
  FParam := Param;
end;

谢谢!

【问题讨论】:

  • 我们怎么可能知道这是否有意义?我们看不到所有的代码。也许您有充分的理由这样做。也就是说,我想不出什么好理由,所以我预测代码是假的。

标签: delphi constructor overloading


【解决方案1】:

如果我希望第一个代码运行,那么在第二个代码中调用它是否有意义并且也继承了先调用父构造函数?

没有。因为您的第一个构造函数应该自己调用继承的构造函数,所以最后继承的构造函数会被调用两次,这很可能不会发生。

否则,如果你的无参数TMyType.Create() 没有调用继承的,那么它就不是一个合适的构造函数,应该被删除。

所以正确的做法是这样的:

constructor TMyType.Create(Param: TObject); overload;
begin
  Create();
  FParam := Param;
end;

constructor TMyType.Create();  overload;
begin
  inherited Create(); // for both constructors

  ...some common code
end;

但是在 Delphi 中还有另一种可能性。

constructor Create; overload;
constructor Create(Param: TObject); overload;
procedure AfterConstruction; override;


constructor TMyType.Create(Param: TObject); 
begin
  inherited Create(); 

  FParam := Param;
end;

constructor TMyType.Create();
begin
  inherited ; 

 ... maybe some extra code
end;

procedure TMyType.AfterConstruction();
begin
    inherited;

  ...some common code
end;

请注意区别,什么时候执行“通用代码”,什么时候执行“FParam := Param;”

在第一种方式中,流程就像

  • 创建(参数)
  • ..创建()
  • ....继承的 Create()
  • ....通用代码
  • ..FParam := 参数;
  • AfterConstruction(空)

在第二个中,顺序会有所不同

  • 创建(参数)或创建()
  • ..继承的 Create()
  • ..FParam := 参数;
  • 施工后
  • ..通用代码

如您所见,这些块的执行顺序颠倒了。


但是,也许您根本不需要多个构造函数?

constructor TMyType.Create(const Param: TObject = nil); 
begin
  inherited; 

 ... Some code

  FParam := Param;
end;

【讨论】:

  • 对隐含的AfterConstruction 感到困惑。最好将公共部分放在方法中并从两个构造函数中调用。
  • 然后你有 10 个具有非平凡依赖图的构造函数,但这仍然很容易。然而,在 2 年内,如果你的班级突然变得混杂起来,另一个人会成为孙子。 YMMV,但我认为 AfterConstruction 是一个非常酷的功能
  • 对于应该简单的不,不要这样做的答案太长了。如果有代码要在两个构造函数中执行,那么该特定代码应该驻留在可以从两个构造函数调用的专用方法中。
  • 我的理解是AfterConstruction的目的是调用无法在构造函数中运行的代码。这是为了克服 Delphi 和 C++Builder 之间的差异,因为虚拟方法处理(TCustomForm 和组件中的类似使用)的差异。
  • @petervonča 尽管如此,Delphi 不允许将构造函数作为方法调用。
【解决方案2】:

是的,您的代码非常合理,并且构造函数的调用完全符合预期。

Delphi 对象模型支持调用继承构造函数的构造函数和不调用继承构造函数的构造函数。

如果你不确定,试试这个:

program Project5;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TMyBase = class
    constructor Create;
  end;

  TMyType = class(TMyBase)
    constructor Create; overload;
    constructor Create(Param: TObject); overload;
  end;

constructor TMyBase.Create;
begin
  Writeln('TMyBase.Create');
end;

constructor TMyType.Create;
begin
  Writeln('TMyType.Create');
end;

constructor TMyType.Create(Param: TObject);
begin
  inherited Create;
  Create;
  Writeln('TMyType.Create(Param)');
end;

begin
  TMyType.Create(TObject.Create);
  Readln;
end.

【讨论】:

  • 不调用inherited的构造函数不是正确的构造函数。两个构造函数都需要调用inherited。如果一个构造函数需要调用另一个构造函数,那么不要在第一个构造函数中调用inherited,让第二个构造函数调用它。 Arioch'The 描述它的方式是正确的。
  • @RemyLebeau - 不调用inherited 的构造函数与调用它的构造函数一样好,就像 Delphi 所关心的那样。我们在这里讨论 Delphi,而不是想象中的完美编程语言
  • 要么遵循常识和传统的继承思想(使用继承的构造函数),要么为“有意义”给出自己的非标准定义
  • @Arioch'C++ 根本不使用继承的构造函数。 Delphi 也可以不用继承的构造函数,没有问题。
  • 所以你对“有意义”的定义是“可以在 Delphi 中编写 C++ 代码”。在我的书中没有多大意义,。在 C++ 中,您可以更好地编写 C++ 代码。
猜你喜欢
  • 2016-07-03
  • 2010-11-02
  • 2020-03-14
  • 2011-03-24
  • 2014-03-12
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
相关资源
最近更新 更多