我在创建动态对象时调用错误的虚拟Create()方法时遇到了问题。父方法被调用而不是decendant方法。为什么在动态对象创建期间Delphi调用不正确的构造函数?
我已经审查了这些帖子,但无法弄清楚:
Delphi - Create class from a string
Exploring TRTTIType and Descendants
Can I pass a Class type as a procedure parameter
我有以下类别:
TCellObj = class(TPhysicsObj)
...
public
constructor Create(RgnMgr : TObject); virtual; //RgnMgr should be TRgnManager
destructor Destroy;
...
end;
TCellObjClass = Class of TCellObj;
--------------------------------
TCellTrialAObj = class(TCellObj)
...
public
...
constructor Create(RgnMgr : TObject); virtual; //RgnMgr should be TRgnManager
end;
--------------------------------
TRgnManager = class (TObject)
...
public
function NewCell(ClassRef : TCellObjClass) : TCellObj;
...
end;
....
function TRgnManager.NewCell(ClassRef : TCellObjClass) : TCellObj;
var CellObj : TCellObj;
begin
CellObj := ClassRef.Create(Self);
CellObj.DefaultInitialize;
CellObj.Color := TAlphaColors.Slategray;
FCellsList.Add(CellObj); //This will own objects.
SetSelection(CellObj);
Result := CellObj;
end;
最后我通过以下行启动动态对象创建的过程:
RgnManager.NewCell(TCellTrialAObj);
我的目标是有TRgnManager.NewCell创建基于传过来的参数派生类TCellObj的任何子孙。我将在使用过程中将结果转换为适当的类类型。
当我用NewCell中的调试器遍历代码时,Evaluate/Modify工具告诉我ClassRef = TCellTrialAObj与预期的一样。
但是,当我踏进ClassRef.Create(个体经营)线,它进入TCellObj .Create(),而不是TCellTrialAObj.Create(),因为我本来期望。这是我不明白的部分。
将结果分配给CellObj后,Evaluate/Modify工具告诉我CellObj.ClassName ='TCellTrialAObj';因此,ClassRef是TCellTrialAObj,那么Create()函数为什么不调用TCellTrialAObj.Create()?
在此先感谢。
P.S.我使用Embarcadero®德尔福10西雅图版本23.0.22248.5795
附录
我拼凑低于此功能,使用从上面的链接的例子。它似乎工作,并根据需要调用TCellTrialAObj.Create。但我不明白如何,为什么,或者如果我真的做得对。谁能解释一下?
function TRgnManager.NewCell(ClassRef : TCellObjClass) : TCellObj;
var CellObj : TCellObj;
RT : TRttiType;
C : TRttiContext;
T : TRttiInstanceType;
V : TValue;
begin
C := TRttiContext.Create;
T := (C.GetType(ClassRef) as TRttiInstanceType);
V := T.GetMethod('Create').Invoke(T.metaClassType,[self]);
C.Free;
CellObj := V.AsObject as TCellObj;
//CellObj := ClassRef.Create(Self);
CellObj.DefaultInitialize;
CellObj.Color := TAlphaColors.Slategray;
FCellsList.Add(CellObj); //This will own objects.
SetSelection(CellObj);
Result := CellObj;
end;
你淹没在警告和提示中,或者你为什么错过编译器告诉你什么是错的? –
析构函数也应该覆盖它。您可以在TRgnManager上使用前向声明,以便它可以用作参数。代码中的许多问题比您确定的单个问题还多。 –
@StefanGlienke和DavidHeffernan感谢您的反馈。看到其他评论,因为我试图教育自己,并避免未来类似的问题。 – kdtop