【问题标题】:How to free object contained in another object [closed]如何释放另一个对象中包含的对象[关闭]
【发布时间】:2014-04-21 20:06:23
【问题描述】:

我正在使用 Delphi 2010 并且有一个关于释放对象的问题。

假设我有如下代码,如果发生异常,我想清除 TProduct 和 TPart。

如何释放正确包含的对象 TPart ?

//Clases are defined like this
TProduct = class(TRemotable)
private
  FName: String;
  FAge: Integer;
  FColor: String;
  FPart: TPart;  
published
  property Name: String read FName write FName;
  property Age: Integer read FAge write FAge;
  property Color: String read FString write FString;
  property Part: TPart read FPart write FPart;  
end;

TPart = class(TRemotable)
private
  FName: String;
  FColor: String;  
published
  property Name: String read FName write FName;
  property Color: String read FString write FString;
end;


//Then in a method, code will get info from database, create objects and fill them
function MyFunction: TProduct;
begin
  Result:=nil;

  query.Open;
  Result:=TProduct.Create;
  try
    try
      Result.Name:=query.FieldByName('NAME').AsString;
      Result.Age:=query.FieldByName('AGE').AsInteger;
      Result.Color:=query.FieldByName('COLOR').AsString;
      ...
      if (Result.Color='Blue') then
      begin
        Result.Part:=Part.Create;
        Result.Part.Name:='Bottle';
        Result.Part.Color:='Green';
      end;
    except
      on e: Exception do
      begin
        //If exception occurred, I want to make sure 
        //that both TProduct and TPart objects are freed properly
        FreeAndNil(Result); //works fine
        FreeAndNil(Result.Part); //<-- WON'T COMPILE - Get "Constant object cannot be passed as var parameter"
        Part.Free; //<--COMPILES but isn't FreeAndNil better?
      end;
    end;
  finally
    query.Close;
  end;
end;

我不是要重新设计代码,只是为了确保如果创建了 TPart,它也会被释放?

【问题讨论】:

  • B从何而来?它是在哪里定义的?
  • 这是假代码。请提供真实代码。 A := A.Create 是错误的。该代码不会运行。你不提供任何类型,所以我们不知道什么是什么。您将B 用作类型和变量。这不可能是正确的。 FreeAndNil 接收无类型的 var 参数。您很可能正在尝试将属性作为参数传递。这是不允许的。您可以直接使用Free。您的对象所有权处理完全被破坏了。你不能继续这种疯狂的所有权方法。你肯定漏了很多。启用内存泄漏检查。在异常处理程序中释放对象很奇怪。
  • *我不是要重新设计代码。" 它需要重新设计。
  • 很好,要么有两个声明(BA.B)而且它们混淆了,要么这不是真正的代码。但是,是的,A := A.Create 不起作用。
  • @DavidHeffernan 和 Jerry Dodge 我已经更新了代码。非常感谢

标签: delphi oop delphi-2010


【解决方案1】:

正确的方法是让A拥有B的所有权,让A的析构函数释放B。这样,您的异常处理程序只需要担心释放A,如果它是在引发异常之前创建的,它将释放B

type
  ClassA = class
  public
    B: ClassB;
    destructor Destroy; override;
  end;

destructor ClassA.Destroy;
begin
  B.Free;
  inherited;
end;

var
  A: ClassA;
begin
  ...
  A := ClassA.Create;
  try
    ...
    A.B := ClassB.Create;
    ...
  except
    on e: Exception do
    begin
      FreeAndNil(A); // or A.Free;
      ...
    end;
  end;
  ...
end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多