【发布时间】:2017-05-24 17:30:12
【问题描述】:
我在动态对象创建期间调用了不正确的虚拟 Create() 方法时遇到问题。调用父方法而不是子方法。
我已经查看了这些帖子,但无法弄清楚:
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(self) 行时,它会转到 TCellObj.Create(),而不是像我预期的那样转到 TCellTrialAObj.Create()。这是我不明白的部分。
将结果分配给 CellObj 后,评估/修改工具告诉我 CellObj.ClassName = 'TCellTrialAObj';
所以ClassRef是TCellTrialAObj的,那为什么Create()函数没有调用TCellTrialAObj.Create()??
提前致谢。
附:我正在使用 Embarcadero® Delphi 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 感谢您的反馈。在我尝试自我教育并避免将来出现类似问题时,请查看其他 cmets。