Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.11.14;
Скачать: CL | DM;

Вниз

Стиль: саморазрушение   Найти похожие ветки 

 
Igorek ©   (2002-10-30 20:22) [0]

Сегодня был такой случай: уничтожается обьект, метод которого в стеке вызовов процедур. Естественно, если после уничтожения мы в этом методе обратились бы к каким-либо полям данного (уже уничтоженного) обьекта - получили бы AccessViolation. К счастью мы этого не сделали и все нормально работает. Но не является ли такой подход признаком плохого стиля?


 
down   (2002-10-30 20:58) [1]

то есть Destroy вызвается из метода объекта? по-моему это не есть нормально


 
down   (2002-10-30 21:02) [2]

хотя, вообще-то, при использовании подсчета ссылок это есть нормально...
вообще, обращаться к полям оьъекта после вызова destroy - это несколько ошибочно, какая разница - из метода он вызывается или нет


 
Юрий Зотов ©   (2002-10-30 21:52) [3]

В подобной ситуации я использовал отложенное уничтожение - посылкой форме сообщения через PostMessage. То есть, сначала завершается вызов метода объекта, а потом он уничтожается извне.

Думаю, так лучше. И не мешает обращаться к полям.


 
down   (2002-10-30 22:14) [4]

>В подобной ситуации я использовал отложенное уничтожение -
>посылкой форме сообщения через PostMessage
по моему скромному мнению, это есть как раз плохой стиль - нужно связывать объект с формой, да и навороченно слишком... "keep it simple, stupid!" :)


 
Andryk ©   (2002-10-30 22:35) [5]

Как раз здесь Юрий Зотов прав.

Ну например посмотрите как уничтожается форма по событию OnClose. Попробуйте внутри обработчика вызвать Free и AccessViolation вам гарантирован, именно поэтому там есть параметр Action если его вернуть со значением caFree, форма уничтожится самой VCL когда "закончится" стек вызовов.


 
down   (2002-10-30 23:01) [6]

Одно дело форма, другое - какой-то отвлеченный объект, который может, например, использоваться в бесформенном приложении. Правоту Юрия я не оспариваю(потому и написал - "по моему скромному мнению"), иногда, может быть, его способ - хорошее решение.


 
Юрий Зотов ©   (2002-10-30 23:54) [7]

> нужно связывать объект с формой
Совершенно не обязательно.

> и навороченно слишком
IMHO, это нормальный уровень прикладного программиста.

> который может использоваться в бесформенном приложении.
Нет проблем. PostThreadMessage + Application.OnMessage.


Вообще же, я привел этот пример не как абсолютное решение, а именно как пример обхода нежелательной ситуации. Скажем, таким же образом можно выгружать DLL, из которой показана модальная форма, но, наверное, могут встретиться и ситуации, когда этот способ окажется неприемлем.


 
down   (2002-10-31 00:30) [8]

> нужно связывать объект с формой
Совершенно не обязательно.

- Ну не с формой, так с другим объектом, причем связь получается притянутой за уши.

> и навороченно слишком
IMHO, это нормальный уровень прикладного программиста.

- Если можно сделать проще, то нужно делать проще, мы ведь говорим о стиле.

> который может, например, использоваться в бесформенном приложении.
Нет проблем. PostThreadMessage + Application.OnMessage.

- Пример я привел неверный, правильный - консольное приложение


> Вообще же, я привел этот пример не как абсолютное решение,
> а именно как пример обхода нежелательной ситуации.


- Я же просто хотел сказать, что, ИМХО, такой способ не есть гут и лично я бы в общем случае предпочел уничтожать объект именно изнутри. Вообще, конечно, нужно думать и применять то, что в конкретной задаче более целесообразно.


 
Cobalt ©   (2002-10-31 00:35) [9]

Предполагаю, что один из доводов Против саморазрушения объекта - то, что он не может установить указатель на себя в Nil.


 
Юрий Зотов ©   (2002-10-31 00:42) [10]

> Cobalt © (31.10.02 00:35)

1. Такого указателя может вообще не быть.

2. Таких указателей (на один и тот же объект) может быть сколько угодно много.

3. Такие указатели к самому объекту не относятся, а за какие-то там внешние переменные он не отвечает и НИЧЕГО с ними делать не должен.


 
Anatoly Podgoretsky ©   (2002-10-31 00:42) [11]

Это только плюс, глобальные в могилу, источник неприятностей, для работыы как правило ссылки, за редким исключением не нужны


 
KSergey ©   (2002-10-31 08:45) [12]

Что за блажь уничтожать объектом самого себя?! Разве он себя создавал? Нет. Создавался он извне. Так значит и уничтожить надо извне.

to Anatoly Podgoretsky © (31.10.02 00:42)

Ой, а еще раз русской речью можно? ;) вроде буквы то русские, но я ничего не понял....

> Cobalt © (31.10.02 00:35)
> Предполагаю, что один из доводов Против саморазрушения объекта
> - то, что он не может установить указатель на себя в Nil.

Люди! Зачем присваивать переменной-ссылке nil? Я никогда этого не делаю, может я что-то недопонмаю? Часто в примерах вижу места, когда написано:

Obj.Free;
Obj:=nil;

и далее Obj нигде не используется (а то и вообще конец ф-ции). Зачем?! Дурацкая привычка?


 
Anatoly Podgoretsky ©   (2002-10-31 09:10) [13]

KSergey © (31.10.02 08:45)
См. Юрий Зотов © (31.10.02 00:42)

Наличие глобальных указателей на объект приводит к ошибка и к искушению повторно использовать переменные, результат один неустойивая программ с трудно обнаруживаемыми ошибками.
Далее ты и сам ссылаешься на Obj:=nil; данная строка предполагае, что переменная Obj будет использоваться повторно где нибудь в конструкциях типа if Assifned(Obj) then ...

Часты также ошибки следующего рода, допустим у нас есть форма TForm1 и соответствующая переменная Form1. В программах при этом часто встречается конструкция

Procedure ....
Var
Form1: TForm1;
begin
Form1 := TForm1.Create

и где то в другом месте обращение к глобальной переменной Form1.xxx ужасть, искать тяжело.
Первое что надо сделать в модуле формы удалить Var Form1: TForm1;


 
SVM (Perm)   (2002-10-31 10:03) [14]

Зачем присваивать Nil? Иногда нужно бывает проверять,
создан ли объект, если нет (Nil), то создать и инициализировать
переменную. К тому же, объект может несколько раз уничтожаться
(FreeAndNil), а затем создаваться снова.


 
Толик ©   (2002-10-31 10:40) [15]

to Anatoly Podgoretsky © (31.10.02 09:10)
Абсолютно в Вами согласен, насчёт удаления Var Form1: TForm1; из модуля формы, да и вообще любых глобальных переменных, но зачем же Boralnd так настоёчиво предлагает использовать глобальные переменные? (понимаю, что вопрос не лично к Вам), да и создать главную форму приложения (Application.MainForm) без глобальной переменной надо ещё понять как сделать...


 
Igorek ©   (2002-10-31 10:55) [16]


> Толик © (31.10.02 10:40)
но зачем же Boralnd так настоёчиво предлагает использовать
> глобальные переменные?

Потому, что Обжект Паскаль - примитивный язык (нет статических переменных, нет областей видимости).
Только не кидайтесь памидорами :-)


 
Zemal ©   (2002-10-31 11:00) [17]

Кстати, чтобы корректно обработать такую ситуацию есть простая конструкция определения существования объекта.
if Assign(Source: TPersistent) then ...
Но это также не предупредит разрушения объекта во время выполнения процедуры (если она длительная) :(. Это я к тому, что если есть потоки... Да и в общем-то надо учесть, что Assign проверяет не существование объекта, а лишь ссылку (не равна ли она nil)... вот в общем-то и всё что он делает :(. Так что вариант: разрушать объекты, как было сказано выше, надо FreeAndNil(TObject)... это гарантированно разрушит объект и присвоит ссылке значение равное nil. Удачи!


 
Igorek ©   (2002-10-31 11:04) [18]

В идеале должно быть так, что-бы обьект можно было разрушить откуда угодно. И для каждого метода (не классового) предусловием было-б существование обьекта. Т.е. если обьекта нет - метод просто не вызывается. Но это уже фантазии.


 
Zemal ©   (2002-10-31 11:24) [19]

Аха :). Фантазии :). Размечтался тут понимаешь-ли :). А вообще... Как бы круто было, в натуре, иметь метод в действительности определяющий существование объекта (причём любого, а не конкретного) в памяти... идилия полнейшая!!! И сразу жить хочется... И писать, писать, писать! хех... ладно, хватит мечтать :).


 
Song ©   (2002-10-31 11:32) [20]

2Юрий Зотов © (31.10.02 00:42)
>>Нет проблем. PostThreadMessage + Application.OnMessage.
А зачем нужен объект TApplication, если нет форм?


 
kva   (2002-10-31 11:38) [21]

Полностью согласен с Ю.Зотовым, down, Andryk, Anatoly Podgoretsky.

Вопрос Ю.Зотову
> В подобной ситуации я использовал отложенное уничтожение -
> посылкой форме сообщения через PostMessage. То есть, сначала
> завершается вызов метода объекта, а потом он уничтожается
> извне.
> Думаю, так лучше. И не мешает обращаться к полям.

А почему не воспользоваться Form1.Release
Результат тот же, а реализация проще.
Или я чего не понял?
С уважением, Владимир.




 
reonid ©   (2002-10-31 11:44) [22]

2Zemal © (31.10.02 11:00)
Assign - это совсем из другой оперы.
а Assigned(x) - это просто x<>nil
(Для процедурных типов @x<>nil).
Никакой магической проверки на существование
объекта тут нет и быть не может.

Igorek © (31.10.02 11:04)
>если обьекта нет - метод просто не вызывается.

Такой "стиль" программирования может привести к
непредсказуемым результатам. (Даже не может, а
безо всякого сомнения приведёт).

Уж лучше пусть эксепшн выдаёт.


 
reonid ©   (2002-10-31 11:52) [23]

2kva (31.10.02 11:38)
>А почему не воспользоваться Form1.Release
А это тоже самое. Только речь шла не только о формах.


 
Zemal ©   (2002-10-31 12:03) [24]

>> reonid
Ты прав... я напутал :). Действительно Assigned... окончание упустил :). Спасибо за уточнение :). А на счёт "магической проверки на существование тут нет": так я же так и написал, что проверяется не равность ссылки nil и ничего больше :). Про магию я неупоминал! :)


 
KSergey ©   (2002-10-31 12:32) [25]

> Zemal © (31.10.02 11:24)
> Аха :). Фантазии :). Размечтался тут понимаешь-ли :). А
> вообще... Как бы круто было, в натуре, иметь метод в действительности
> определяющий существование объекта (причём любого, а не
> конкретного) в памяти... идилия полнейшая!!! И сразу жить
> хочется...

Не понятно, что тут хорошего, впрочем это легко (как мне кажется) реализуемо: свой менеджер объектов - и вперед! Не так уж и сложно, и главное - все возможности для этого есть.


 
Юрий Зотов ©   (2002-10-31 12:40) [26]

> Song © (31.10.02 11:32)

Какая разница? GetMessage устроит?
Мы о словах говорим, или о принципах?


 
Anatoly Podgoretsky ©   (2002-10-31 12:41) [27]

Толик © (31.10.02 10:40)
Создать можно, но переменные для этой формы и дата модуля могут иметь право на существование, остальные лишнее, нормально и спокойно жить без них.


 
Zemal ©   (2002-10-31 13:35) [28]

>>KSergey
Аха, с тобой согласен, нужно писать менеджер объектов, в котором отображать состояние объектов и действия с ними... вот только это "мартышкин труд", да и нафига такое делать? Легче в деструкторе объекта к примеру прописать такое: "OK := False;", а в методе: "if not OK then Abort;". И все проблемы :).


 
Tano   (2002-10-31 22:35) [29]


> Zemal © (31.10.02 13:35)

IMHO, Вы в последнем сообщении погорячились - после выполнения деструктора объекта не станет и само обращение к его методу выдаст Access V...(никак не запомню как пишется :). То есть "OK" проверять негде будет.


 
evgeg ©   (2002-10-31 22:53) [30]

> Igorek © (31.10.02 10:55)

Сейчас закидаем.

Пример статической переменной:

var s: double;

Область видимости: в модулях interface и implemetation, в классах published, public, protected, private.

Учите матчасть и не говорите полной ерунды.

Насчет вызова деструктора из метода объекта. В VCL это используется в методе Free. В нем сначала проверяется, равен ли Self nil и если нет, вызывается деструктор.
Для корректной работы Free и нужно выставление объекта в nil.
Используется это в конструкторах и деструкторах.

type
TMyObj = class
FSomeObject: TSomeObject;
end;

constructor TMyObj.CReate;
begin
...
FSomeObject := TSomeObject.Create;
...
end;

destructor TMyObj.Destroy;
begin
...
FSomeObject.Free;
end;


Если в конструкторе произойдет исключение, вызовется деструктор Destroy, в котором будут освобождены только проинициализированные поля-объекты, т. к. при выделении памяти (перед вызовом конструктора) поля объекта обнуляются.


 
evgeg ©   (2002-10-31 22:55) [31]

> само обращение к его методу выдаст Access V...(никак не запомню как пишется :)

Только обращение к вирт. методу или к полю. Вызов стат. метода не приведет к Access Violation.


 
Igorek ©   (2002-11-01 17:06) [32]


> evgeg © (31.10.02 22:53)
> > Igorek © (31.10.02 10:55)
>
> Сейчас закидаем.
...

Не буду спорить, но неубедительно.;-)
Статические переменные я имел ввиду видимые в пределах метода.
Область видимости в Паскале одна в пределах модуля.
Простите, если задел за живое.


 
AlexKniga ©   (2002-11-01 18:45) [33]

2 Igorek
Procedure MyProc;
Const МояСтатическаяПеременная: TМояСтатическаяПеременная;
Begin
End;


 
evgeg ©   (2002-11-01 18:52) [34]

> Статические переменные я имел ввиду видимые в пределах метода

Это называется локальной переменной. Учите терминологию!


 
Мышь   (2002-11-01 20:03) [35]

Есть такой метод - Notification, вызываемый разрушающимся объектом, для того, чтобы уведомить другой объект, содержащий ссылку на разрушающийся. Вот в нем, как раз, и удобно обNILлить ссылку.


 
Igorek ©   (2002-11-04 12:42) [36]


> evgeg © (01.11.02 18:52)
> Это называется локальной переменной. Учите терминологию!

Не нравиться мне Ваш преподавательский тон. Ну да ладно.
Локальная статическая переменная - видимая в пределах метода, выделяется память и инициализируется при загрузке программы, сохраняет свое значение между вызовами метода, допускает переприсваивание.

2 AlexKniga
Не допускается переприсваевание. :-(


 
Бурундук   (2002-11-04 13:43) [37]

AlexKniga прав - есть такая недокументированная
фича паскаля:
локальные типизированные константы сохраняют значение между
вызовами.

>Не допускается переприсваевание. :-(
Тут Вам не здесь. :)))
В паскале разрешается присваивание
типизированным константам.
(Есть, правда, опция компилятора, запрещающая это,
но по умолчанию она выключена)


 
Igorek ©   (2002-11-04 16:28) [38]

procedure f;
const
I: Integer = 0;
begin
Inc(I);
end;


Как сделать, что-бы компилировалось и выполнялось?


 
down   (2002-11-04 16:30) [39]

в опциях проекта поставить галочку напротив "Assignable typed constants"


 
Bis ©   (2002-11-04 16:49) [40]

может я упустил смысл темы, но есть замечательный метод
FreeAndNil
и вызывать можно вроде где угодно и не ругаться на Паскаль


 
Igorek ©   (2002-11-04 17:03) [41]


> down (04.11.02 16:30)
> в опциях проекта поставить галочку напротив "Assignable
> typed constants"

Спасибо. Но тогда получаются константы не настоящие, если их можно "взломать" фишкой компилятора.


 
evgeg ©   (2002-11-04 19:05) [42]

> Не нравиться мне Ваш преподавательский тон.

А мне не нравится, что вы утверждаете ерунду, не разобравшись в вопросе.

> Но тогда получаются константы не настоящие, если их можно "взломать" фишкой компилятора.

Получается, что типизированные константы являются статическими переменными. Нетипизированные константы являются настоящими константами.


 
Igorek ©   (2002-11-05 11:00) [43]


> Получается, что типизированные константы являются статическими
> переменными. Нетипизированные константы являются настоящими
> константами.

Спасибо за разъяснение. Ошибаться может каждый - я был неправ. К счастью Паскаль не мой родной язык.


 
Sectey ©   (2002-11-05 11:16) [44]

Совершенно согласин с evgeg.

вот пример

Const
i = 10;
Var
p : ^integer;
begin
p := @i;
-> здель компилятор ругается благим матом 37. riable required
p^ := 40;
end;


а тут все ок

Const
i : integer = 10;
Var
p : ^integer;
begin
p := @i;
p^ := 40;
end;

в результате i = 40

Такойже фокус проходит и с

TTr = class
private
FCount : integer;
...
public
property Count: integer read FCount;
...
end;

Var
tr : TTr;
p : ^integer;
begin
p := @tr.Count;
p^ := 40;
end;

в результате tr.Count = 40


 
Бурундук   (2002-11-05 11:47) [45]

2Sectey © (05.11.02 11:16)
Зачем такие сложности?
Можно и так:

const
i: integer = 10;
begin
i := 40;
// типизированная константа - она совсем никакая
// не константа (без {$WRITEABLECONST OFF}или{$J-}),
// а самая что ни на есть переменная.
end;



Страницы: 1 2 вся ветка

Текущий архив: 2002.11.14;
Скачать: CL | DM;

Наверх




Память: 0.6 MB
Время: 0.023 c
7-46161
kofman
2002-09-10 20:38
2002.11.14
Как получить список запущенных приложений


3-45704
Ренат
2002-10-23 10:54
2002.11.14
Таблицы foxpro


1-45976
Dennis S
2002-11-04 14:38
2002.11.14
работа с диалогом Find


14-46143
vopros
2002-10-28 11:01
2002.11.14
Мужики я вернулся.Не надалго.Пока тоска на душе моей,


1-45875
Strumpf
2002-11-04 22:05
2002.11.14
Эмуляция фокуса на внутренней форме