这段时间在对照侯老师的《深入浅出MFC》学习Delphi,有一个问题提出来供大家讨论,也就是Delphi下对象的动态生成问题,即给定一个代表类名的字符串,希望生成该类的一个实例。
。VC下面对象的动态生成实现原理
大家都知道VC下面对象的动态生成实现原理,其核心有两点:
1、利用C++里面支持类的静态成员变量的特点,使每个支持实例动态生成的类都有一个包含该类CRunTimeClass指针和类名字符串的结构类型的静态成员变量;
2、利用C++结构类型里面定义结构或类类型的变量时自动调用该结构或类的构造函数的特点将该静态成员变量插入到一个全局范围的型别网中;
这样在要生成动态生成类实例的时候,只需要遍历该型别网,根据类名字符串找到该类的静态成员变量,根据其CRunTimeClass指针调用相应的函数就可生成类的实例。
。Delphi下面对象的动态生成的实现(以生成窗口为例)
1、需在project单元里面调用RegisterClass(窗口类名)函数对类进行注册;
2、在需要动态生成的地方调用以下代码:
function DynaCreateForm(szFormClass):TForm;
var
form:TForm;
pc:TPersistentClass;
begin
pc:=GetClass(szFormClass);
Application.CreateForm(TComponentClass(pc),form);
result:=form;
end;
。缺陷分析
C++里面对对象动态的支持在类类部就可实现,而在Delphi里面因为没有静态成员变量(虽然可以用全局变量代替,但从封装性方面考虑效果较差)以及要显式调用类的构造函数,因此虽可实现,但在封装性和便利性比起C++要差多了。
。VC下面对象的动态生成实现原理
大家都知道VC下面对象的动态生成实现原理,其核心有两点:
1、利用C++里面支持类的静态成员变量的特点,使每个支持实例动态生成的类都有一个包含该类CRunTimeClass指针和类名字符串的结构类型的静态成员变量;
2、利用C++结构类型里面定义结构或类类型的变量时自动调用该结构或类的构造函数的特点将该静态成员变量插入到一个全局范围的型别网中;
这样在要生成动态生成类实例的时候,只需要遍历该型别网,根据类名字符串找到该类的静态成员变量,根据其CRunTimeClass指针调用相应的函数就可生成类的实例。
。Delphi下面对象的动态生成的实现(以生成窗口为例)
1、需在project单元里面调用RegisterClass(窗口类名)函数对类进行注册;
2、在需要动态生成的地方调用以下代码:
function DynaCreateForm(szFormClass):TForm;
var
form:TForm;
pc:TPersistentClass;
begin
pc:=GetClass(szFormClass);
Application.CreateForm(TComponentClass(pc),form);
result:=form;
end;
。缺陷分析
C++里面对对象动态的支持在类类部就可实现,而在Delphi里面因为没有静态成员变量(虽然可以用全局变量代替,但从封装性方面考虑效果较差)以及要显式调用类的构造函数,因此虽可实现,但在封装性和便利性比起C++要差多了。
function DynaCreateForm(szFormClass):TForm;
begin
Result:=GetClass(szFormClass).Create(Application);
end;
function DynaCreateForm(szFormClassLstring):TForm;
多研究一下再下结论
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TLineObj=class(TPersistent)
end; TLineObjClass=class of TLineObj; TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
LineObj:TLineObj;
begin
try
LineObj:=TLineObjClass(GetClass('TLineObj')).Create ;
finally
LineObj.Free;
end;
end;Initialization
RegisterClass(TLineObj);end.