在Delphi构造函数中覆盖,虚拟/动态

时间:2013-06-29 14:06:33

标签: delphi methods constructor virtual-method

虚拟/动态

// declare in Child Class
constructor Create; virtual;

constructor TChildClass.Create;
begin
  inherited;
end;

有覆盖的那个。

// declare in Child Class
constructor Create; override;

constructor TChildClass.Create;
begin
  inherited;
end;

没有任何东西

// declare in Child Class
constructor Create;

constructor TChildClass.Create;
begin
  inherited;
end;

这些是一回事吗?看起来很混乱。

2 个答案:

答案 0 :(得分:5)

是的,存在差异,但我们首先使用更基本的OOP术语来处理virtual关键字,但它仍然适用于Delphi方法。

当您声明派生(子)类并将方法实现为“覆盖”时,这意味着您将覆盖(惊讶)基类的匹配方法。

这意味着您可以编写如下代码:

var child : TBaseClass;
begin
    child := TChildClass.Create; // note that it is stored in TBaseClass variable
    child.VirtualMethodDefinedInBaseClassThatHasBeenOverriddenInChildClass;

这将调用子类中的方法,即使该变量被定义为基类类型也是如此。这是虚方法的全部目的,您可以通过更通用的类型的引用来访问对象,并且仍然调用为您正在处理的特定类型的对象编写的方法。

如果你在基类中有一个虚拟方法,你选择不在子类中重写,而是重新引入,那么在某些情况下你会有效地替换它。请注意,在大多数情况下,您需要告诉编译器您确实打算这样做,尽管我不确定Delphi在这里需要什么。

基本上,如果您的变量是TBaseClass类型,并且您在其上调用了一个虚拟方法,那么它已经在TChildClass中重新引入,它仍然会在基类中调用该方法。

但是,如果您的变量属于TChildClass类型,并且您在其上调用该方法,则会获得新方法。

现在,对于构造函数,在Delphi中,它略有不同。

虚拟构造函数的要点是能够虚拟构造对象,为此,Delphi也有“类类型”。

你可以这样说:

type TClassToUse = class of TBaseClass;
var cls : TClassToUse;
    obj : TBaseClass;
begin
    cls := TChildClass;
    obj := cls.Create;

(请注意,我的Delphi知识在这里有点生疏,如果有人发现上述代码中的错误或明显问题,请告诉我或者只是解决它)

这里我们在变量中存储一个“类”,然后让类请为我们构造一个对象。这允许我们切换出要创建的类,但是我们还需要声明我们想要使用虚拟的构造函数,否则我们会遇到问题。

所以在上面的代码中,如果你在TBaseClass中将构造函数声明为虚拟,然后在TChildClass中覆盖它(代码实际上在cls中使用),则被覆盖的构造函数将被使用

另一方面,如果您没有将构造函数声明为虚拟,我们将返回基类构造函数。 Virtual基本上意味着找出在运行时执行的正确方法,而非虚拟方法将在编译时计算出来。

如上述常规方法所述的重新引入,也是这样的。

但是,虚拟构造函数仅在通过类类型使用时用作虚拟。

答案 1 :(得分:1)

不,静态和虚拟方法不是一回事。

overridevirtual方法的一种情况。

http://en.wikipedia.org/wiki/Virtual_function

http://docwiki.embarcadero.com/RADStudio/XE4/en/Methods#Method_Binding

构造函数在这里没有什么特别之处 - 它们符合与问题的其他方法相同的规则