类类型和构造函数调用

时间:2009-08-06 14:27:35

标签: delphi delphi-2009

如果我写

type
  MyClass = class of TMyClass;
...
Obj := MyClass.Create;

调用正确的构造函数(TMyClass中的构造函数)。

如果我写

var
  ClassVar : TClass;
...
ClassVar := TMyClass;
Obj := ClassVar.Create;

只调用TObject构造函数。

为什么呢?这两个版本有什么区别?我可以在第二种情况下强制执行TMyClass构造函数调用吗?

4 个答案:

答案 0 :(得分:11)

TClass在system.pas中声明为“Class of TObject”。调用什么构造函数是在编译时决定的,所有编译器都知道你正在使用什么基类。它不知道变量运行时的值是什么,所以它必须默认为基类。如果您使用的是TClass,那么您的基类是TObject。

如果您正在使用类变量,我假设您有某种层次结构,并且您正在尝试实施工厂。如果要确保在运行时根据类变量的值调用正确的构造函数,而不是在编译时代码中包含的内容,则需要一个虚拟构造函数。

type
  TMyBaseObject = class(TObject)
  public
    constructor Create; virtual;
  end;

  TMyClass = class of TMyBaseObject;

使用TMyClass而不是TClass作为类变量,现在编译器将生成对TMyBaseObject.Create的调用,该调用是虚拟的。确保所有派生类都覆盖基本构造函数,并且最终会在运行时调用正确的类。

答案 1 :(得分:4)

TObject.Create不是虚拟的,您需要将ClassVar声明为具有虚拟构造函数的类的classtype。

答案 2 :(得分:2)

我建议你研究一下覆盖由TObject引入的AfterConstruction方法,以使像这样的多态性工作。

每个类定义都可以引入一个新的构造函数,它有自己的一组参数。如果基类是变量,则类变量只知道构造函数。这是可能的,因为构造函数既不是虚拟的也不是重写的。您可以在基类上标记构造函数virtual,并标记所有降序类覆盖,这会阻止参数列表。 (我想如果你忘了'覆盖',编译器会警告你的新构造隐藏虚拟构造。)

答案 3 :(得分:-3)

或者从已经有虚拟构造函数的TComponent下载它。