Сделайте копию объекта для использования позже - PullRequest
0 голосов
/ 05 июня 2018

У меня есть компонент со следующим классом:

TResp=Class
...

TRespostasPendentes = class(TObjectList)
   private
      fSaldoAPagar : Double;
      function GetSaldoRestante : Double;
      function GetTotalPago : Double;
      function GetTotalDesconto : Double;
   protected
      procedure SetObject (Index: Integer; Item: TResp);
      function GetObject (Index: Integer): TResp;
   public
      function Add (Obj: TResp): Integer;
      procedure Insert (Index: Integer; Obj: TResp);
      property Objects [Index: Integer]: TResp
        read GetObject write SetObject; default;

      property SaldoAPagar   : Double read fSaldoAPagar write fSaldoAPagar ;
      property TotalPago     : Double read GetTotalPago ;
      property TotalDesconto : Double read GetTotalDesconto ;
      property SaldoRestante : Double read GetSaldoRestante ;
   end;

Мне нужно сделать копию объектов в TRespostasPendentes, чтобы использовать их позже после освобождения.

Исходный класс не реализует метод Assign().

Я попробовал следующий код, но я получаю нарушение прав доступа при освобождении копии.

Что яделать неправильно?

Я не могу изменить исходный класс.

RespostasPendentes:=TRespostasPendentes.Create;
//Here I fill some properties of RespostasPendentes
RP:=TRespostasPendentes.Create;
try
  RP.Assign(RespostasPendentes);
  RespostasPendentes.Free; 
finally
  RP.Free; -->Access Violation
end;

1 Ответ

0 голосов
/ 05 июня 2018

Свойство TObjectList.OwnsObjects по умолчанию имеет значение True.TObjectList наследует Assign() от TList, что по умолчанию просто копирует указатели из списка источников.

Таким образом, вы получаете два TObjectList объекта, которым оба "принадлежат"«тот же набор объектов, и, таким образом, вы получаете AV, когда один список пытается освободить те же объекты, что уже освобожден другим списком.

Чтобы предотвратить освобождение объектов в первом списке, вам необходимо:

  • установить для 1-го списка OwnsObjects значение False после копирования указателей объектов на 2-й список.

    RespostasPendentes := TRespostasPendentes.Create;
    // ...
    RP := TRespostasPendentes.Create(False); // <-- False initially in case Assign() fails...
    try
      RP.Assign(RespostasPendentes);
      RespostasPendentes.OwnsObjects := False; // <-- add this 
      RP.OwnsObjects := True; // <-- take ownership of the copied pointers
      RespostasPendentes.Free; 
      // use RP as needed...
    finally
      RP.Free;
    end;
    
  • Extract() указатели объектов из 1-го списка, позволяющие ему отказаться от владения без освобождения объектов, а затем добавить указатели во 2-й список.

    RespostasPendentes := TRespostasPendentes.Create;
    // ...
    RP := TRespostasPendentes.Create;
    try
      RP.Capacity := RespostasPendentes.Count;
      while RespostasPendentes.Count > 0 do
      begin
        Obj := RespostasPendentes.Objects[0];
        RespostasPendentes.Extract(Obj); // <-- remove ownership
        try
          RP.Add(Obj); // <-- take ownership
        except
          Obj.Free;
          raise;
        end;
      end;
      RespostasPendentes.Free; 
      // use RP as needed...
    finally
      RP.Free;
    end;
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...