如果我写
type
MyClass = class of TMyClass;
...
Obj := MyClass.Create;
调用正确的构造函数(TMyClass中的构造函数)。
如果我写
var
ClassVar : TClass;
...
ClassVar := TMyClass;
Obj := ClassVar.Create;
只调用TObject构造函数。
为什么呢?这两个版本有什么区别?我可以在第二种情况下强制执行TMyClass构造函数调用吗?
答案 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下载它。