"Delphi总是先构造派生的类,仅当派生类调用了继承的构造器时才去构造基类。在C++中次序相反,从祖先类开始构建,最后才是派生的类。因而,假如有类C继承于B,而B继承于A,那么Delphi先是构建C,然后是B最后是A.C++先构建A,然后B,最后C。" 想必有很多人曾经读过段话;
问题:“Delphi总是先构造派生的类,仅当派生类调用了继承的构造器时才去构造基类”
1、“构造”是指什么?(希望答的具体准确一点)编译器具体要做什么??
2、前后两个“构造”含义一样吗?具体讲,就是编译器做的工作一样吗?
问题:“Delphi总是先构造派生的类,仅当派生类调用了继承的构造器时才去构造基类”
1、“构造”是指什么?(希望答的具体准确一点)编译器具体要做什么??
2、前后两个“构造”含义一样吗?具体讲,就是编译器做的工作一样吗?
2、前后两个“构造”含义不一样,前者的构造是一个概念,而后者的构造是一个动词,通过构造器来构造基类。
constructor原理我还是知道的;例如 Obj1:=Tobj.create;
编译器将其编译实现为:
用TObj对应的VMT为依据,调用TObject的Create构造函数。而在Create构造函数调用了系统的ClassCreate过程,系统的ClassCreate过程又通过存储在类VMT调用NewInstance虚方法。调用NewInstance方法的目的是要建立对象的实例空间,若没有重载该方法,它就是TObject类的NewInstance。TObject类的NewInstance方法将根据编译器在VMT表中初始化的对象实例尺寸(InstanceSize),调用GetMem过程为该对象分配内存,然后调用InitInstance方法将分配的空间初始化。InitInstance方法首先将对象空间的头4个字节初始化为指向对象类对应VMT的指针,然后将其余的空间清零。建立对象实例之后,还调用了一个虚方法AfterConstruction。最后,将对象实例数据的地址指针保存到Obj1变量中,这样,Obj1对象就诞生了。 我现在有点疑惑的地方是:
怎样理解这句话:“Delphi总是先构造派生的类,仅当派生类调用了继承的构造器时才去构造基类”
假如 A:=Class;···B:=Class(A) 若A有自己的构造函数,B继承A的。
那么在bo:B; bo:=B.Create;执行过程中。编译器是调用A类的构造函数来实现的。编译器应该是先构造B类,再构造A类;构造B类当然是创建对象bo必不可少的过程,那么构造A类具体是什么含义(难道要创建一个A类的对象??)?我觉得只能说是调用A类的构造函数来创建bo。请大家帮忙讲讲;
***************
这样写有点问题,这样会出错的吧?B继承A的话,B的Create是先重载A的Create,然后再做B的初始化工作的。
“B继承A的话,B的Create是先重载A的Create,然后再做B的初始化工作的。”
“先重载A的Create”那分配的对象空间大小是A的呢?还是B的呢?(不考虑初始化)创建出的对象是A的呢?还是B的呢?
>>的ClassCreate过程,系统的ClassCreate过程又通过存储在类VMT调用NewInstance虚方法。
>>调用NewInstance方法的目的是要建立对象的实例空间,若没有重载该方法,它就是TObject
>>类的NewInstance。TObject类的NewInstance方法将根据编译器在VMT表中初始化的对象实例
>>尺寸(InstanceSize),调用GetMem过程为该对象分配内存,然后调用InitInstance方法将
>>分配的空间初始化。InitInstance方法首先将对象空间的头4个字节初始化为指向对象类对
>>应VMT的指针,然后将其余的空间清零。建立对象实例之后,还调用了一个虚方法
>>AfterConstruction。最后,将对象实例数据的地址指针保存到Obj1变量中,这样,Obj1对
>>象就诞生了。bo: B;
bo := B.Create;
因为调用的的B,所以bo的InstanceSize也是就是B类的对象的InstanceSize。创建的当然是B类的对象。你说的那几句用引号引起来的话是那里听来的阿?是原话吗?说真的,如果单从字面上去理解,真的是骇人听闻的,呵呵
为对象分配内存是在一进CREATE就进行的,如果B没有重载A的CREATE,B还是有自己CREATE(从A继承得来),而不是调用A的CREATE。如果B重载了CREATE并且inherited;这才是调用A的CREATE,这时候就必须构造A了。 TBase = class
private
fname:string;
public
constructor Create(AOwner:TComponent);
end; Tsub = class(TBase)
public
constructor Create(AOwner:TComponent);
end;
procedure TForm1.Button1Click(Sender: TObject);
var fb:TBase;fsub:TSub;
begin
fb:=TBase.Create(self);
showmessage(fb.fname);
fsub:=TSub.Create(self);
showmessage(fsub.fname);
end;
{ TBase }constructor TBase.Create(AOwner: TComponent);
begin
self.fname:='Base';
end;{ Tsub }constructor Tsub.Create(AOwner: TComponent);
begin
inherited; //如果没有这行,不调用父类的Create
end;
谢谢citytramper(阿琪),谢谢各位的参与,结帐!