Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2002.11.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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
и вызывать можно вроде где угодно и не ругаться на Паскаль



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

Форум: "Основная";
Текущий архив: 2002.11.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.014 c
14-46137
Beginner-Designer
2002-10-28 11:40
2002.11.14
как устанавливать программы в Linux?


3-45690
boa
2002-10-28 09:23
2002.11.14
Краткий справочник по MS SQL


1-45880
NeyroSpace
2002-11-05 14:00
2002.11.14
Как узнать какой компонент породил Exception?


3-45747
Beglec
2002-10-21 17:27
2002.11.14
Сложный вопрос по SQL


6-46024
SVIN
2002-09-18 09:23
2002.11.14
Народ помогите плз с сокетами





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский