Форум: "Основная";
Текущий архив: 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.55 MB
Время: 0.008 c