这是对象:
TCell = class(TPersistent)
private
FAlignmentInCell :byte;
public
constructor Create; virtual;
published
property AlignmentInCell:byte read FAlignmentInCell write FAlignmentInCell;
end;
这是它的构造函数:
constructor TCell.Create;
begin
inherited;
FAlignmentInCell:=5;
end;
这是一个函数,它动态创建从TPersistent派生的任何对象(参数是以字符串形式提供的类名)
function CreateObjectFromClassName(AClassName:string):TPersistent;
var DynamicObject:TPersistent;
TempObject:TPersistent;
DynamicPersistent:TPersistent;
DynamicComponent:TComponent;
PersistentClass:TPersistentclass;
ComponentClass:TComponentClass;
begin
PersistentClass:=TPersistentclass(FindClass(AClassName));
TempObject:=PersistentClass.Create;
if TempObject is TComponent then
begin
ComponentClass:=TComponentClass(FindClass(AClassName));
DynamicObject:=ComponentClass.Create(nil);
end;
if not (TempObject is TComponent) then
begin
DynamicObject:=PersistentClass.Create; // object is really TCell, but appropriate constructor seems to be not called.
end;
result:=DynamicObject;
end;
我的想法是创建这样的新Cell(TCell):
procedure TForm1.btn1Click(Sender: TObject);
var p:TPersistent;
begin
p := CreateObjectFromClassName('TCell');
ShowMessage(IntToStr(TCell(p).AlignmentInCell)); // it is 0. (Why?)
end;
当我想检查AlignmentInCell属性时,我得到0,但我预计为什么?为什么?有办法解决吗?
答案 0 :(得分:2)
编译器无法确定类型TPersistentClass
的变量在运行时将保留的值。所以他假设它正是:TPersistentClass
。
TPersistentClass
被定义为class of TPersistent
。 TPersistent
没有虚构造函数,因此编译器不会包含动态查找实际类的VMT中构造函数的地址的调用,而是对唯一匹配构造函数的{硬编码'调用{{ 1}}具有:从它的基类TObject继承的那个。
这可能是我不知道的原因的决定,但如果您选择将TPersistent
定义为以下
TCell
您不需要TCell = class(TComponent)
private
FAlignmentInCell: byte;
public
constructor Create(AOwner: TComponent); override;
published
property AlignmentInCell:byte read FAlignmentInCell write FAlignmentInCell;
end;
以及TempObject
函数中的所有决策(以及其他人指出的可能泄漏):
CreateObjectFromClassName
并确保管理function CreateObjectFromClassName(AClassName:string): TComponent;
var
ComponentClass:TComponentClass;
begin
ComponentClass:=TComponentClass(FindClass(AClassName));
Result := ComponentClass.Create(nil);
end;
的生命周期,因为它没有Result
。