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