我有一个方法,它构造一个对象,调用一个Execute方法,并释放该对象.对象的类型由传递给方法的TClass后代确定.注意这是我正在谈论的Delphi for Win32,而不是.NET.
编辑:我应该指出这是Delphi 2006,因为在下面的答案中已经注意到,在将来的版本中可能不需要NewInstance调用.但就我而言,这是必需的.因此,我会想象我的问题的答案(它是否安全?并且CreateForm()是否有潜在的泄漏)需要在此基础上回答这是Delphi 2006
编辑#2:似乎为D2007和D2009提供的解决方案确实适用于D2006.我必须从早期版本的Delphi中获得"NewInstance"的习惯......
function TPageClassFactory.TryExecute(ScrnClass: TCustomPageClass): boolean; //TCustomPageClass = class of TCustomPage var ScrnObj: TCustomPage; //TCustomPage defines an abstract Execute() method begin Result := FALSE; //default ScrnObj := TCustomPage(ScrnClass.NewInstance); //instantiate try ScrnObj.Create(Self); //NB: Create() and Execute() are *virtual* methods ScrnObj.Execute; finally FreeAndNil(ScrnObj); end; Result := TRUE; end;
我想知道的是这是否安全 - 如果Create()引发异常,会发生什么?
从Forms.pas.TApplication.CreateForm()看一个类似的例子,对异常处理采取了不同的方法(我已经删除了下面不相关的位):
procedure TApplication.CreateForm(InstanceClass: TComponentClass; var Reference); var Instance: TComponent; begin Instance := TComponent(InstanceClass.NewInstance); TComponent(Reference) := Instance; try Instance.Create(Self); except TComponent(Reference) := nil; raise; end; end;
在Forms.pas方法中,这是否意味着在Create()方法中发生异常时内存泄漏?我的理解是InstanceClass.NewInstance分配了内存,因此在这种情况下内存没有被释放/释放/释放?
你应该把创建放在try finally块之外.
但更好的解决方案是:
type TMyClass = class () public constructor Create(...); virtual; function Execute: Boolean; virtual; end; TMyClassClass = class of TMyClass; procedure CreateExecute(const AClass: TMyClassClass): Boolean; var theclass : TMyClass; begin theclass := AClass.Create; try Result := theclass.Execute; finally theclass.Free; end; end;