Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как объекту удалить самого себя? При закрытии формы удалить ее объект 
V
    Опции темы
RomanEEP
Дата 10.1.2010, 22:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 5
Всего: 8



Цитата(shmelina @  10.1.2010,  19:36 Найти цитируемый пост)
Не уверен, что это безопасно.Ты вызываешь Free, управление программой переходит в метод Free, там объект уничтожается, затем идет возврат из процедуры Free в метод FormFreed, которого уже нет, т. к. объект освобожден.

Процедура объекта ничем не отличается от обыкновенной процедуры  (с тем отличием что у процедуры объекта есть скрытый параметр - указатель на объект располагающийся в регистре EAX). По поэтому из любой процедуры объекта можно беспрепятсвенно удалить объект. Просто нужно понимать, что после удаления указатель на объект недействителен и нельзя обращаться к полям, свойствам и методам объекта. Компилятор "автоматически" к ним НИКОГДА обращаться не будет, поэтому если в твоем коде нет обращений к данным объекта после удаления - все отлично работает.
В большинстве событий объектов после вызова обработчика идет обращения к каким либо данным объекта, поэтому вызывать Free или Destroy внутри обработчика событий и не рекомендуется. Хотя вполне возможно.

Цитата(shmelina @  10.1.2010,  19:36 Найти цитируемый пост)
Так тоже не хорошо. Форма в принципе не должна ничего знать о TModul. Это плохой стиль программирования.

Если форма не будет знать про TModul она В ПРИНЦИПЕ не сможет его удалить. Чудес не бывает. Нельзя удалить не зная что. Точнее можно, но результат будет непредсказуемый, это "плохой стиль програмирования")))

PM MAIL   Вверх
shmelina
Дата 10.1.2010, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



А корректно ли будет у объекта TModul сделать обработчик события закрытия формы и выполнить Free?
Код

destructor TModul.Destroy;
begin
  Form.Free;
  inherited;
end;

procedure TModul.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Free;
end;

PM MAIL   Вверх
RomanEEP
Дата 10.1.2010, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 5
Всего: 8



Нет. Будет такая цепочка вызовов:
TForm.DoClose->TModul.FormClose->TModul.Destroy->TForm.Destroy
после выполнения TForm.Destroy при возврате в TForm.DoClose результат один - AV 
PM MAIL   Вверх
shmelina
Дата 10.1.2010, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Цитата(RomanEEP @  10.1.2010,  22:45 Найти цитируемый пост)
Нет. Будет такая цепочка вызовов:
TForm.DoClose->TModul.FormClose->TModul.Destroy->TForm.Destroy

Скорее так:
TForm.DoClose->TModul.FormClose->TForm.Destroy->TModul.Destroy
Но это наверно не меняет смысла.
PM MAIL   Вверх
RomanEEP
Дата 10.1.2010, 23:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 5
Всего: 8



если точнее, то:
TForm.DoClose->TModul.FormClose->TModul.Free->TModul.Destroy->TForm.Free->TForm.Destroy
хотя в нашем случае разницы нет
PM MAIL   Вверх
shmelina
Дата 10.1.2010, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Т.е. ты предлагаешь в деструкторе формы удалять объект?
Тогда наверно можно так?
Код

procedure TModul.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TModul.FormDestroy(Sender: TObject);
begin
  Form := nil;
  Free;
end;

destructor TModul.Destroy;
begin
  if Assigned(Form) then
    Form.Free;
  inherited;
end;


Это сообщение отредактировал(а) shmelina - 10.1.2010, 23:22
PM MAIL   Вверх
bems
Дата 11.1.2010, 04:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



Код

type
  TModul = class(TComponent)
  private
    Form: TForm;
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{ TModul }

constructor TModul.Create(AOwner: TComponent);
begin
  inherited;
  Form := TForm.Create(Self);
  Form.Show;
end;

end.


Это сообщение отредактировал(а) bems - 11.1.2010, 04:34


--------------------
Обижено школьников: 8
PM MAIL   Вверх
shmelina
Дата 11.1.2010, 09:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



bems, спасибо за идею. Совсем забыл про это. Если по другому не получится - вернуть к ней.

То, что я написал в предыдущем посте, корректно?

Теперь нужно в контейнере удалить этот объект. В общем у меня получилось так (тестовый проект):
Код

unit MainFo;

interface

uses ModlList,
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TMainForm = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    ModulList: TModulList;
  end;

var
  MainForm: TMainForm;

implementation

uses Modl;

{$R *.dfm}

procedure TMainForm.Button1Click(Sender: TObject);
begin
  ModulList.ShowModul(mtOne);
end;

procedure TMainForm.Button2Click(Sender: TObject);
begin
  ModulList.ShowModul(mtTwo);
end;

procedure TMainForm.Button3Click(Sender: TObject);
begin
  ModulList.ShowModul(mtThree);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
  ModulList := TModulList.Create(Self);
end;

procedure TMainForm.FormDestroy(Sender: TObject);
begin
  ModulList.Free;
end;

end.

Код

unit ModlList;

interface

uses Modl,
  Generics.Collections, Classes;

type
  TModulList = class(TObjectList<TModul>)
  private
    Owner: TComponent;
    procedure ModulFormDestroy(AModul: TModul);
  public
    constructor Create(AOwner: TComponent);
    function ShowModul(AModulType: TModulType): TModul;
  end;

implementation

{ TModulList }

constructor TModulList.Create(AOwner: TComponent);
begin
  inherited Create;
  Owner := AOwner;
end;

procedure TModulList.ModulFormDestroy(AModul: TModul);
var
  I: Integer;
begin // Удаляем модуль - его форма только что умерла
  for I := Count - 1 downto 0 do 
    if Items[I] = AModul then
      Delete(I);
end;

function TModulList.ShowModul(AModulType: TModulType): TModul;
var
  I: Integer;
begin
  Result := nil;
  // Ищем модуль. Он может быть уже создан.
  for I := 0 to Count - 1 do
    if Items[I].ModulType = AModulType then
    begin
      Result := Items[I];
      Result.Show;
      Break;
    end;
  // Модуль не создан. Создаем.
  if not Assigned(Result) then
  begin
    Result := TModul.Create(Owner, AModulType);
    Result.OnFormDestroy := ModulFormDestroy;
    Add(Result);
  end;
end;

end.

Код

unit Modl;

interface

uses
  Forms, Classes, SysUtils;

type
  TModul = class;

  TModulType = (mtOne, mtTwo, mtThree);
  TNotifyModul = procedure(AModul: TModul) of object;

  TModul = class
  private
    Form: TForm;
    FModulType: TModulType;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
  public
    OnFormDestroy: TNotifyModul;
    constructor Create(AOwner: TComponent; AModulType: TModulType);
    destructor Destroy; override;
    property ModulType: TModulType read FModulType;
    procedure Show;
  end;

implementation

{ TModul }

constructor TModul.Create(AOwner: TComponent; AModulType: TModulType);
begin
  inherited Create;
  FModulType := AModulType;
  Form := TForm.Create(AOwner);
  Form.Caption := IntToStr(Ord(AModulType) + 1);
  Form.OnClose := FormClose;
  Form.OnDestroy := FormDestroy;
  Form.Show;
end;

destructor TModul.Destroy;
begin
  // Формы может уже не быть, если ее закрыл сам пользователь.
  if Assigned(Form) then
    Form.Free;
  inherited;
end;

procedure TModul.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TModul.FormDestroy(Sender: TObject);
begin
  Form := nil;
  OnFormDestroy(Self);
end;

procedure TModul.Show;
begin
  Form.Show;
end;

end.


Исходники прилагаю (delphi 2009). Посмотрите, пожалуйста. FastMM теперь молчит как партизан.

Это сообщение отредактировал(а) shmelina - 11.1.2010, 09:38

Присоединённый файл ( Кол-во скачиваний: 3 )
Присоединённый файл  FreeSelf.zip 2,44 Kb
PM MAIL   Вверх
shmelina
Дата 12.1.2010, 16:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 5.6.2009

Репутация: нет
Всего: нет



Никто не ответил - ну и ладно. Главное помогли и все работает. Спасибо за помощь!
Наберу 100 сообщений - все поставлю плюсы smile.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0963 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.