如何解决Delphi根据TObject类型调用虚拟构造函数
我有一个从TStringList对象派生的对象,该对象称为“ TAutoString”。创建列表时,它允许您指定对象类型。然后,每次将新条目添加到字符串列表时,它还会创建与该字符串条目关联的对象的副本。这样可以轻松地将各种其他信息与每个字符串一起存储。例如:
type TMyObject = class(TObject)
public
Cats: integer;
Dogs: integer;
Mice: integer;
end;
MO := TAutoString.Create(TMyObject);
在对象内部,类信息存储在类变量中:
private
ObjectClass: TClass;
constructor TAutoString.Create(ObjClass: TClass);
begin
inherited Create;
ObjectClass:=ObjClass;
end;
现在,每次添加新项目时,它都会创建指定类型的新对象:
function TAutoString.Add(const S: string): Integer;
begin
Result:=inherited Add(S);
Objects[Result]:=ObjectClass.Create;
end;
我现在可以添加或读取与每个字符串条目关联的信息。
TMyObject(MO.Objects[25]).Cats := 17;
D:=TMyObject(MO.Objects[25]).Dogs;
这很好用,因为该对象没有构造函数。如果对象具有构造函数,则创建对象时不会调用其构造函数,因为TObject的构造函数不是虚拟的。
谁能想到解决此问题的方法。我已经看到了使用RTTI库的解决方案,但这是在没有RTTI库的Delphi-7中。
顺便说一句,TObject的构造函数不是虚拟的似乎有些奇怪。如果可以的话,它将启用各种有用的功能,例如我正在尝试实现的功能。
编辑:雷米(Remy)的以下建议只是我所需要的。我最初尝试过类似的策略,但无法使其起作用。当它似乎没有按照我认为的方式工作时,我认为对于虚拟方法肯定有些不了解的地方。他的职务促使我再次审视它。原来,我已经为要附加的对象的构造函数放弃了“ Override”指令。现在,它按应有的方式工作。
我担心的另一个问题是,我已经在许多其他基于对象“ TObject”的应用程序中使用了自动字符串,并且我不想返回并更改所有代码。我通过重载构造函数并为基于TObject的对象提供了一个构造函数,而为我的TAutoClass对象提供了另一个解决方案来解决该问题:
constructor Create(ObjClass: TAutoClass); overload; virtual;
constructor Create(ObjClass: TClass); overload; virtual;
根据调用哪个构造函数,对象类存储在不同的变量中。
private
AutoClass: TAutoClass;
ObjectClass: TClass;
然后,在构造对象时,我检查一下已分配的对象并使用该对象:
procedure TAutoString.CreateClassInstance(Index: integer);
begin
if AutoClass<>nil then Objects[Index]:=AutoClass.Create
else Objects[Index]:=ObjectClass.Create
end;
新版本可与任何一种对象完美配合。
解决方法
要执行所需的操作,必须为列表对象定义一个派生自其的基类,然后可以向该类添加虚拟构造函数。您的ObjectClass
成员将必须使用该类类型,而不是使用TClass
。
例如:
type
TAutoStringObject = class(TObject)
public
constructor Create; virtual;
end;
TAutoStringObjectClass = class of TAutoStringObject;
TAutoString = class(TStringList)
private
ObjectClass: TAutoStringObjectClass;
public
constructor Create(ObjClass: TAutoStringObjectClass);
function Add(const S: string): Integer; override;
...
end;
...
constructor TAutoStringObject.Create;
begin
inherited Create;
end;
constructor TAutoString.Create(ObjClass: TAutoStringObjectClass);
begin
inherited Create;
ObjectClass := ObjClass;
end;
function TAutoString.Add(const S: string): Integer;
var
Obj: TAutoStringObject;
begin
Obj := ObjectClass.Create;
try
Result := inherited AddObject(S,Obj);
except
Obj.Free;
raise;
end;
end;
...
然后,您只需将派生对象类调整为使用TAutoStringObject
而不是TObject
,例如:
type
TMyObject = class(TAutoStringObject)
public
...
constructor Create; override;
end;
MO := TAutoString.Create(TMyObject);
...
将按预期方式调用其构造函数。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。