另外,与C++中不同的是,Delphi为构造函数定义了另一种方法类型(mkConstructor,参见Delphi安装目录下的\Source\RTL\Common\typInfo.pas,125行),我们可以把它理解为 “特殊的”类方法。它只能通过类(类名/类引用/类指针)来调用,而一般的类方法既可以通过类也可以通过对象来调用;还有一点特殊就是构造函数中内置的self参数是指向对象的,而在类方法中self是指向类的,我们通常在其中对其数据成员进行初始化工作,使其成为真正意义上的对象,这都得益于self这个参数。
在默认情况下,构造函数是静态函数,我们可以把它设为虚方法,在其派生类中对其覆载(Override),这样可以实现构造函数的多态性(参见2.4),也可以对其进行重载(Overload),创建多个构造函数,还可以在派生类直接覆盖(Overlay)父类的构造函数,这样在派生类屏蔽了父类的构造函数,在VCL中就采用了这些技术,形成一个构造&析构的“体系结构”(参见4)
2.2 对象的创建的全过程
对象的创建完整过程应该包括分配空间、构造物理数据结构、初始化、内部子对象的创建。上面提到,构造函数只是负责初始化工作以及调用内部子对象的构造函数,那么分配空间和构造物理结构是怎么完成的呢?这由于编译器在做了额外的事情,我们不知道而已。编译到构造函数时,会构造函数之前,会在插入一行“call @ClassCreate”汇编代码,它实际上就是system 单元中的_ClassCreate函数,下面看看_ClassCreate函数的部分源码:
function _ClassCreate(AClass: TClass; Alloc: Boolean): TObject;
asm
{ -> EAX = pointer to VMT }
{ <- EAX = pointer to instance }
…
CALL dword ptr [EAX].vmtNewInstance //调用NewInstance
…
End; {\Source\RTL\sys\system.pas,第8939行}
VmtNewInstance=-12; 它是NewInstance 函数在类中的偏移量,则“CALL dword ptr [EAX].vmtNewInstance”实际上就是调用NewInstance,请看TObject.NewInstance:源码:
class function NewInstance: TObject; virtual;
class function TObject.NewInstance: TObject;
延伸阅读
文章来源于领测软件测试网 https://www.ltesting.net/