在 Delphi 中有没有一种方法可以通过类信息参数动态地进行类型转换?

of1yzvn4  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(138)

当使用一个传递参数的类时,我在理解类型转换时遇到了一些困难。我试着搜索这个问题,但没有找到其他答案。
我正在使用一些遗留的Delphi代码,使用的是Delphi 2006,它不支持泛型(在Delphi 2009中引入)。
代码使用TList来存储指向特定类型的示例化类的指针。当清除列表时,它们使用以下代码:

procedure ClearList(AList: TList);  
  var i: Integer;
  begin
    for i := 0 to AList.Count - 1 do
      TObject(AList[i]).Free;
    AList.Clear;
  end;

它的名字是这样的:

ClearList(FExtraVisitTypes);
  ClearList(FDiagnoses);
  ClearList(FProcedures);
  ClearList(FImmunizations);
  ClearList(FSkinTests);
  ClearList(FPatientEds);
  ClearList(FHealthFactors);
  ClearList(FExams);

我对这一点的理解可能不正确,但我担心如果将指向的对象作为TObject释放,则不会调用后代对象的析构函数,这可能会导致内存泄漏(我的多态学功夫有点生疏,这可能会引起我的困惑)。
因此,我尝试将清除功能更改为:

procedure ClearList(AList: TList; ItemClass: TPCEItemClass);  //mod to add ItemClass
  var i: Integer;
  begin
    for i := 0 to AList.Count - 1 do begin
      (AList[i] as ItemClass).Free;
    end;
    AList.Clear;
  end;

TPCEItemClass的定义如下:

TPCEItemClass = class of TPCEItem;

然后,我将清除调用更改为:

ClearList(FExtraVisitTypes, TPCEProc);
  ClearList(FDiagnoses, TPCEDiag);
  ClearList(FProcedures, TPCEProc);
  ClearList(FImmunizations, TPCEImm);
  ClearList(FSkinTests, TPCESkin);
  ClearList(FPatientEds, TPCEPat);
  ClearList(FHealthFactors, TPCEHealth);
  ClearList(FExams, TPCEExams);

但编译器不允许这样做,并给出以下错误:

[Pascal Error] uPCE.pas(1730): E2015 Operator not applicable to this operand type

对于此错误行:

(AList[i] as ItemClass).Free;

问题:
1.最初的编码方式,即通过简单地调用great-great-great(etc)祖先Free方法来释放项,最终会影响后代的析构函数方法吗?在我写这篇文章的时候,我现在认为它确实会影响后代的析构函数方法。但我不知道为什么。所以任何能帮助我记住这一点的答案都是很好的。
1.为什么我尝试通过class类型的参数进行类型转换的方法不起作用?这是不允许的吗?还是我的语法有问题?有没有别的方法可以做到这一点?
1.我是不是搞错了?有更好的办法吗?
谢谢

agxfikkp

agxfikkp1#

我担心的是,如果将指向的对象作为TObject释放,则不会调用后代对象的析构函数,这可能会导致内存泄漏。
对于正确实现的类来说,情况并非如此。
所有类都派生自TObjectTObject.Free()调用TObject.Destroy()析构函数,即virtual。任何需要析构逻辑的后代必须override该析构函数(如果不这样做,则存在需要修复的缺陷)。
因此,在正确编写的代码中,原始代码将如图所示完美地工作。在任何 * 有效 * 和 * 正确实现 * 的对象上调用Free()将调用其最派生的析构函数。
话虽如此,多年来,当类需要析构函数时,有很多人忘记了override析构函数,从而导致了你所担心的内存泄漏,所以,确保你注意你的类在做什么,你会没事的。
所以我试着把clear函数修改如下......但是编译器不允许这样做,并给出这个错误
正确,因为你不能像你试图做的那样,在一个使用变量的对象上执行类型转换到元类类型。类型转换需要在编译时指定目标类型,但是元类变量直到运行时才被赋值。
最初的编码方式,即通过简单地调用great-great-great(etc)祖先Free方法来释放项,最终会影响后代的析构函数方法吗?
原始代码在99%的情况下都能正常工作,是的。大多数 Delphi 代码编写者都很擅长在适当的时候使用override析构函数。但是剩下的1%只有在你处理那些没有正确实现的类的时候,在这种情况下,修改它们是它们的作者的责任,而不是你修改在它们上面调用Free()的代码的责任。
在我写这篇文章的时候,我觉得它确实是这样的,但我不知道为什么。
虚析构函数的多态调度,就像调用任何其他virtual方法一样。
为什么我尝试通过class类型的参数进行类型转换的方法不起作用?这是不允许的吗?
对。这是违法的。
有别的办法吗?
不(是的,是的,但是它涉及到在运行时手动遍历对象的类结构,但是这需要深入理解编译器如何在内存中布局对象,所以我在这里不打算讨论这个问题)。

相关问题