Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > Повторное использование разрушенных объектов


Автор: boobie 1.4.2016, 17:02
Есть объект, которому вызываем деструктор)
Код

    pr2.Destroy;
//и на всякий случай
    FreeAndNil(pr2);

Можно ли после этого заново вызвать конструктор для объекта и использовать с новыми параметрами? Повторно инициализировать и использовать объект pr2?
Нужно создать динамический массив объектов, толкать в него объекты, ненужные удалять, при этом забивать в освободившиеся ячейки новые объекты, поэтому такой вопрос.

Автор: superVad 1.4.2016, 17:45
Нажми на FreeAndNil с зажатым контролом и посмотри как он устроен. Destroy перед FreeAndNil делать не надо, он в нем вызовется.
У уничтоженного объекта, ничего вызвать нельзя - его нет. И вообще вызывать конструктор у уже созданного объекта тоже незачем.
А переменной pr2 можешь присвоить новый созданный объект, тут проблем нет.

Возможно тебе сгодиться TObjectList.

Автор: Alexeis 1.4.2016, 21:13
Цитата(boobie @  1.4.2016,  18:02 Найти цитируемый пост)
Можно ли после этого заново вызвать конструктор для объекта и использовать с новыми параметрами? Повторно инициализировать и использовать объект pr2?

  Переменная объекта в делфи это указатель. Указатель можно инициализировать сколько угодно раз уничтожая объект или нет. Например форма уничтожает дочерние компоненты сама. Указатель это просто 4 байта. Адрес, который указывает на данные которые хранятся в другом месте. Обычная ячейка памяти как например переменная типа integer.

Автор: boobie 2.4.2016, 08:32
Цитата

Destroy перед FreeAndNil делать не надо, он в нем вызовется.

Похоже, что нет. Я в деструктор затолкал Messagebox, при вызове FreeAndNil, он не вылетает.
Дело в том, что внутри объекта есть другие объекты, которые нужно освободить. Это я делаю в деструкторе, присваивая каждому nil. Динамическим массивам задаю длину в 0.
Что-то я не уверен, что FreeAndNil сделает все это без моего деструктора, а сборщик мусора повел себя странно при работе с таймером (складывалось впечатление, что он не успевает подчищать).
В общем, сейчас делаю так:
Код

if assigned(pr2) then
begin
  pr2.Destroy;
  pr2:=nil;
end;

Если надо использовать для другого нового объекта, то дальше
Код

if (not Assigned(pr2)) then
  begin
    pr2:=myclass.Create();
    pr2.Set1(Blablabla);
  end;
 

Автор: Alexeis 2.4.2016, 10:59
Цитата

Вызов деструктора для несуществующих объектов недопустим и при выполнении программы приведет к ошибке. Чтобы избавить программистов от лишних ошибок, в объекты ввели предопределенный метод Free, который следует вызывать вместо деструктора. Метод Free сам вызывает деструктор Destroy, но только в том случае, если значение объектной переменной не равно nil.

Так что FreeAndNil вызывает ваш деструктор, поскольку он виртуальный, будет вызван именно ваш деструктор. 

Цитата(boobie @  2.4.2016,  09:32 Найти цитируемый пост)
Динамическим массивам задаю длину в 0.

Динамические массивы/строки/интерфейсы это управляемые типы, которые деструктор сам уничтожает.

Если ваш дейструктор не вызывается, то вероятно он как-то неверно описан. Правильное описание деструктора 
destructor Destroy; override;

Автор: boobie 2.4.2016, 12:04
Цитата(Alexeis @  2.4.2016,  10:59 Найти цитируемый пост)
destructor Destroy; override;
destructor Destroy; override; 

Ужас, я override не писал... inherited в деструкторе поставил. А в конструкторе ничего такого делать же не надо?
Теперь Freeandnil нормально работает.

Автор: Alexeis 2.4.2016, 13:34
Цитата(boobie @  2.4.2016,  13:04 Найти цитируемый пост)
А в конструкторе ничего такого делать же не надо?
Теперь Freeandnil нормально работает. 

  Компилятор должен был выдать предупреждение по идее. Только inherited нужно в конструкторе для вызова конструктора предка.

Автор: boobie 2.4.2016, 14:20
Цитата(Alexeis @  2.4.2016,  13:34 Найти цитируемый пост)
Только inherited нужно в конструкторе для вызова конструктора предка.


Вроде, можно не указывать, если наследуешь от TObject.

Если нужно из динамического массива удалить объект (элемент i), то вызываем для объекта FreeAndNil, затем выполняем сдвиг (mas[a]:=mas[a+1]) в цикле от i+1 до конца массива (length-1) , затем вызываем setlength(mas,length-1). Все верно? А проще никак, т.е. если массив длинный, то и перебрать его придется от удаляемого элемента до конца? При присвоении в элемент, который пережил FreeAndNil, ошибки не будет?

Автор: Alexeis 2.4.2016, 15:39
Цитата(boobie @  2.4.2016,  15:20 Найти цитируемый пост)
Вроде, можно не указывать, если наследуешь от TObject.

Да, они пустые.

Цитата(boobie @  2.4.2016,  15:20 Найти цитируемый пост)
Если нужно из динамического массива удалить объект (элемент i), то вызываем для объекта FreeAndNil, затем выполняем сдвиг (mas[a]:=mas[a+1]) в цикле от i+1 до конца массива (length-1) , затем вызываем setlength(mas,length-1). Все верно? 

  Достаточно просто уничтожить объект, а потом вызвать http://docwiki.embarcadero.com/Libraries/Seattle/en/System.Delete

Но для хранение объектов удобнее использовать TObjectList
http://docwiki.embarcadero.com/CodeExamples/XE7/en/Generics_Collections_TObjectList_(Delphi)
С ним код будет намного проще и интуитивнее.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)