![]() |
|
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]()
|
|
| Демо |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
-------------------- |
||||
|
|||||
| CodeMonkey |
|
||||||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Этим должен заниматься не класс. Потому что переменной может вообще не быть. Понимаете, класс работает со своими данными, с тем, что внутри. Переменная - это не его данные, она снаружи, и вообще никак не связана с классом. Но если сильно охота, то можно - в качестве примера посмотрите реализацию Application.CreateForm (вызов смотреть в DPR-файле, а реализацию - в Forms.pas). Но делать так без веских причин я бы не стал.
Потому что Self = nil в деструкторе - это глюк (почему? уже сказал Demo: при вызове из конструктора Self гарантировано не-nil, а при внешнем вызове вы вызываете Free; хотя формально вы вполне можете вызывать TForm(nil).Destroy). Такого не должно быть. А раз не должно быть, то вылететь с access violation - вполне нормальный вариант. Можете не засорять исходники лишними проверками. Только надо понимать, что "достаточно" <> "нужно так делать". Верно.
Сделать можно что угодно:
Но тогда вы сами себе буратино.
Рекомендую почитать. Добавлено через 5 минут и 22 секунды Согласен с bems-ом по поводу деструктора. По той простой причине, что пустой конструктор - это деталь реализации, а не стандарт ООП языка. Вот выйдет Fulcrum - откуда вы знаете, может там в деструкторе что-то будет, чтобы сгладить косяки платформы? Вы уверены, что в FreePascal (подставьте сюда любой компилятор Паскаля, с которым вы не знакомы) деструктор тоже пустой? Но это не главное. А главное в том, что класс может быть изменён в процессе рефакторинга позже. В том числе, он может сменить предка. Вызов унаследованных конструкторов и деструкторов всегда - это простое правило, которое поможет вам избежать потенциальных проблем. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
||||||||||
|
|||||||||||
| Демо |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Да согласен я-) Смысл фразы в том, что нужно всегда знать, что делаешь. Если я знаю в данный момент, что в TObject мне ничего не нужно освобождать, то с полным сознанием и уверенностью могу не вызывать родительский деструктор, учитывая, что другоим колмпилятором я не буду пользоваться... -------------------- |
|||
|
||||
| bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Потому что очень трудно следить за каждым конструктором на предмет озможности исключений. Правильнее считать что исключение может возникнуть в любом месте любого конструктора (собственно это не далеко от истины). Если моих слов не достаточно то вот:
А твой пример ни к селу ни к городу. Ясно, что если деструктор ничего не делает, то и проверять нечего (даже если бы в конструкторе TObject и могло возникнуть исключение) Добавлено через 12 минут и 42 секунды что-то меня не поняли. Я говорил не о вызове унаследованного деструктора, а о том, чтобы всегда писать деструктор так, чтобы он мог разрушать недосозданный объект -------------------- Обижено школьников: 8 |
|||
|
||||
| Демо |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Действительно не поняли. Я-то говорил именно об обязательности вызова родительского деструктора. -------------------- |
|||
|
||||
| bems |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 3400 Регистрация: 5.1.2006 Репутация: 18 Всего: 88 |
Даже если это нехватка памяти или Assert? -------------------- Обижено школьников: 8 |
|||
|
||||
| Демо |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Ну если нехватка памяти, то вряд ли можно что-то ещё сделать. А работу с Assert надо заранее проектировать-) -------------------- |
|||
|
||||
| PsiMagistr |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Ребята, благодарю всех. Огромное СПС! Сейчас читаю информацию предоставленную, CodeMonkey :
Итак как я сделал: Реализация конструктора:
Реализация деструктора:
А в коде кнопки:
Запускать это из самой среды бесполезно - Дельфи споткнется в конструкторе. Поэтому компилирую файл. Все как будто получается. И деструктор вызывается. Но таблички:
Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 12:41 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||||||
|
|||||||||
| CodeMonkey |
|
||||||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
= True - излишне. Это всё равно, что спрашивать "если да равно да то" или "включен ли компьютер" (если бы компьютер был бы выключен, программа не смогла бы задать этот вопрос). Надо:
Это уведомление отладчика сделано исключительно для вашего удобства, чтобы вы могли исследовать ситуацию, приводящую к ошибке, прямо на месте. Если вы не хотите этого делать - просто жмите Continue (в новых Delphi) или Run/Run (в старых). Вы также можете отключить эти уведомления в настройках среды, но я бы не стал этого делать - это исключительно полезный механизм. Вы же сами её заблокировали блоком except. Далее, проверять в except MyObject на nil - излишне, т.к. если вы попали в блок except, то только потому, что создание объекта обвалилось. Это всё равно, что проверять Self <> nil в деструкторе. Поэтому:
А вот и табличка:
Или:
В общем, миллион способов. А выбор зависит от того, зачем это надо, и что вы будете делать дальше. И я бы, на вашем месте, рассказал бы побольше про это. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
||||||||||
|
|||||||||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Я попробую в двух словах. Решил писать ролевую игру. Когда то давно писал на VB первый экземпляр. Получилось. Правда реализовывать ООП я не стал, обошелся процедурным программированием.
Основная текущая задача - зашить в класс работу с файлами. Вот например файл персонажа. Изначально там служебная информация, недоступная игроку. (параметры умолчания). Например: Жизнь-100 Интеллект-50 Ловкость=30 И .т.д. Что это значит. Когда мы создаем нового персонажа, конструктор объекта "Персонаж" читает служебную запись файла, считывает переменные умолчания и на основании этого строит вторую запись - это уже реальный персонаж, доступ к которому имеет игрок. В классе я пытаюсь охватить все возможные нюансы работы с файлами. Например обращение из основной программы: MyObject.Lovkost:=30; к свойству "Ловкость", будет означать не только присвоение, но и запись соответствующей информации в файл. Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 13:04 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| CodeMonkey |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Так, а теперь, внимание, вопрос (С)
Положим вы создаёте персонажа из файла TMyObject.Create('SavedGame01.dat'); Положим файл не найден, заблокирован антивирусом или тупо повреждён - вы выбрасываете исключение, отлично. Но. Дальше-то вы что делаете? А дальше вы обрабатываете эту ошибку, показывая мессагу, производя откат или что там ещё придумаете. Но при этом вы не обращаетесь к MyObject. Почему? Потому что он был не создан. Зачем вам обращаться к несуществующему объекту? Я имею ввиду, что вы просто не доходите до этого кода, например:
Если создание объекта проваливается, то до использования объекта ниже вы не доходите. Именно поэтому я сказал, что ваши попытки сделать MyObJect := nil выглядят очень подозрительно. Как, в целом, узнают, что MyObJect <> nil? По месту выполнения кода. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
CodeMonkey, благодарен безмерно. попробую Вам объяснить в чем штука со всеми нюансами.
Итак, у нас есть файл записей (record). Первая запись данного файла - это служебная информация прототипа. Доступ игрока к ней закрыт. Остальные записи в файле это параметры реальных персонажей. В классе будут ДВА конструктора CreateOpen и CreateNew. Если игрок будет открывать уже созданного персонажа то вызываем конструктор CreateOpen, куда передадим лог-пасс. CreateOpen будет проверять существование файла. Если нет, генерируем сообщение "Не хватает служебных ресурсов". Обваливаем конструктор исключением и закрывем программу. Если файл есть, обходим его ночным дозором , поочередно забираем в переменные-поля параметры каждой записи и сравниваем их лог-пассы с лог-пассом введенным пользователем. Если совпадает то: Грузим конструктором туда все данные из найденной записи. И создаем, наконец, объект. А если не совпадает: Генерируем сообщение "Неверный лог-пасс", обрушиваем конструктор и не создаем объект. Введет пользователь новый лог-пасс, нажмет на кнопочку и... Будет новая попытка создания объекта. Второй конструктор CreatNew занимается другим. Он Проверяет, существует ли файл. Если да, то берет служебную первую запись. Грузит значения в переменные. Берет лог-пасс введенный пользователем снова грузит в переменные (подменяя там формальные значения-умолчания взятые из служебной записи). и наконец создает вторую запись. Вторая запись - действительный персонаж. К нему впоследствии обращается игрок. Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 15:01 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| CodeMonkey |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Ээээ.... ну? Что-то я не понял, что вы хотели сказать.
Зачем тогда вам в этом сценарии обнуление переменной MyObject при неудаче? Если в обоих случаях при исключении вы просто игнорируете переменную и не обращаетесь к ней? P.S. Конструктор не обязательно должен начинаться с Create. Удобно создать два конструктора так:
Ибо вызовы TMyObject.Create(...) и TMyObject.Open(...) смотрятся как-то "читабельнее", нежели TMyObject.CreateNew(...) и TMyObject.CreateOpen(...). Это сообщение отредактировал(а) CodeMonkey - 4.6.2010, 14:48 -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
CodeMonkey, свершенно верно. В реальности в случае обрушения в конструкторе в указателе может остаться даже "мусор умолчания" (хотя по моему по умолчанию указатель равен - nil). Объекта то все равно нет и делать нам нечего.
Но мусор для меня нежелателен, хочу чтоб все под контролем было . Это сообщение отредактировал(а) PsiMagistr - 4.6.2010, 14:58 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Вот еще какая тонкая штука, нюансик.
ДАННЫЙ ВОПРОС СНИМАЕТСЯ. Я голова садовая, совсем забыл, что Free контролирует указатель и только в случае указатель <> Nil вызывает деструктор. Это сообщение отредактировал(а) bems - 4.6.2010, 17:49 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
![]()
|
| Правила форума "Delphi: Для новичков" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Для новичков | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |