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

jus*_*tyy 0 delphi methods constructor virtual-functions

虚拟/动态的

// declare in Child Class
constructor Create; virtual;

constructor TChildClass.Create;
begin
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

有覆盖的那个.

// declare in Child Class
constructor Create; override;

constructor TChildClass.Create;
begin
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

一无所有

// declare in Child Class
constructor Create;

constructor TChildClass.Create;
begin
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

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

ang*_*son 5

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

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

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

var child : TBaseClass;
begin
    child := TChildClass.Create; // note that it is stored in TBaseClass variable
    child.VirtualMethodDefinedInBaseClassThatHasBeenOverriddenInChildClass;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

虚拟构造函数的要点是能够虚拟构造对象,为此,Delphi还具有"类类型".

你可以这样说:

type TClassToUse = class of TBaseClass;
var cls : TClassToUse;
    obj : TBaseClass;
begin
    cls := TChildClass;
    obj := cls.Create;
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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