我有一个从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库的解决方案,但这是在Delphi-7中,它没有RTTI库。
顺便说一句,TObject的构造函数不是虚拟的,这似乎有点奇怪。如果是的话,它将启用各种有用的特性,比如我正在尝试实现的特性。
编辑:雷米下面的建议只是我需要的提示。我最初尝试过一种类似的策略,但我无法让它发挥作用。当它看起来不像我想的那样工作的时候,我想一定有一些关于虚拟方法我不理解的东西。他的帖子迫使我再看一遍。结果是,我没有对要附加的对象的构造函数执行“覆盖”指令。现在它的工作方式正是它应该做的。
我关心的另一个问题是,我已经在许多其他应用程序中使用了Auto,在这些应用程序中,对象是基于"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;新版本完美地适用于两种类型的对象。
发布于 2020-09-11 20:54:08
要做您想做的事情,您必须为要派生的list对象定义一个基类,然后可以向该类添加一个虚拟构造函数。您的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);
...并且它们的构造函数将如预期的那样被调用。
发布于 2021-10-23 10:26:26
下面是一个更干净的解决方案的提示:
可以向Tobject添加虚拟构造函数。
要做到这一点,您需要使用所谓的“类助手”。
下面是一个示例:
type
TobjectHelper = class helper for Tobject
public
constructor Create; virtual; // adds a virtual constructor to Tobject.
end;(我的用例是一个TryCreateObject函数,用于检测对象创建过程中内存不足的情况,包装try除了结束,只返回true/false以防止代码中的try以外块,而是使用更多可控制的逻辑if语句)
班级助教人数最多(?)在Delphi 8及更高版本中介绍的。您的要求是德尔菲7,所以这可能不起作用。
除非您为Windows 95/Windows 98/Windows XP编写代码,否则可能是时候升级到最新版本的Delphi,特别是用于unicode支持的Delphi XE版本,否则您将针对即将过时的老化平台进行编码。
然而,对于Windows 95/Windows 98和Windows,我确实认为Delphi 2007可能有一些用处,我相信它可以编译可以在那些旧的windows平台上运行的代码,但我可能错了。
Delphi的后期版本需要有特定的windows系统dlls,否则构建/编译的可执行文件将无法运行,w95/w98/wxp缺少这些dll。
https://stackoverflow.com/questions/63853776
复制相似问题