![]() |
|
Модераторы: Snowy, MetalFan, bems, Poseidon |
![]()
|
|
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Ребят, предположим у нас есть некий класс и в нем конструктор, куда передается строковый параметр FileName (Имя файла)
Возможно ли внутри реализации самого конструктора сделать проверку на существование файла и в зависимости от того, существует ли он - создавать экземпляр объекта или (если файла нет) выдать предупреждение и либо вовсе не создавать, либо разрушить объект?
Кстати в каком именно месте идет команда на выдачу объекту динамической памяти? Заранее спасибо. Это сообщение отредактировал(а) PsiMagistr - 1.6.2010, 19:21 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| kami |
|
||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 22 Всего: 72 |
Нет. В самом конструкторе разрушать объект нельзя. Можно сделать "отложенное" удаление компонента/класса через PostMessage. В данном случае лучшим выходом будет проверка в основном коде на существование файла и после этого уже вызов/не-вызов конструктора. Например, сделать классовый метод, типа
Afair, перед(во время) вызова конструктора. Ибо в самом конструкторе уже доступны все поля и методы созданного объекта. |
||||
|
|||||
| Демо |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Немного не так. Есть 2 метода. Один указал kami - использовать классовую функцию:
Второй метод - поднимать исключение в конструкторе. На примере того же класса:
При возникновении в конструкторе исключения будет немедленно вызван деструктор, а объект не будет создан. Во этом случае код в деструкторе нужно писать, учитывая, что в конструкторе может возникнуть исключение. -------------------- |
||||
|
|||||
| kami |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1806 Регистрация: 25.8.2007 Где: Санкт-Петербург Репутация: 22 Всего: 72 |
||||
|
||||
| CodeMonkey |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
TFileStream ведь так работает.
-------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
СПА-СИ-БО ВСЕМ! 1). А как именно можно словить это исключение в деструкторе? Ну хотя бы примерно? (Просто я о классах исключений слышал, но не более того. Очень поверхностно.) 2) Что есть "классовая функция"? (Даже не слыхал о таком.) Ребята, когда-то я писал ролевую игру на VB. Несмотря на то что я бросил проект, не могу сказать, что он не удался, т.к. все заложенные функции работали исправно, работа с файлами тоже была. Можно было даже бои устраивать и опыт набирать. Но там все было реализовано на уровне процедурного программирования. Ну не считая компонентов брошенных на формы. )))) Теперь мне в голову стукнуло - зашить всю начинку вовнутрь класса Сущность и его производных (Персонаж-Монстр), создать объекты и пусть все свершается в них, чтобы больше с этой рутинной работой не колебаться хотя бы внутри кода основного модуля. P.S. Потратил 2 часа написал на Дельфи "Пятнашки" (головоломка такая). Код вышел стремный, от балды, но работает. Это сообщение отредактировал(а) PsiMagistr - 2.6.2010, 08:55 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| Демо |
|
||||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
А зачем в деструкторе его отдавливать? Задача деструктора - освободить ресурсы и выполнить заключительные процедуры перед уничтожением.
Эту фразу надо понимать так: в деструкторе необходимо проверять, а действительно ли были в конструкторе выделены необходимые ресурсы. В большинстве случаев это простейшие проверки: if Assigned() и т.п. class function/procedure - специальный вид функций, которые могут выполняться без создания экземпляра класса, не имеют доступа к ссылке на экземпляр класса (Self). Пример приведён выше. -------------------- |
||||
|
|||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Гм... Признаться не совсем понял. Ведь если ты сумел вызвать Free (деструктор) объекта, то значит сам объект уже был создан. Ведь он создается сразу при входе в конструктор. Раз объект создан - память под него выделена. Зачем же нужны проверки - была ли выделена память?
Можно ли проверить в деструкторе, выделенна ли в конструкторе память так: If self <> nil then либо, if Assigned(self) = true then Это сообщение отредактировал(а) PsiMagistr - 2.6.2010, 10:36 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| Демо |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1278 Регистрация: 3.11.2005 Репутация: 7 Всего: 50 |
Проверять нужно не сам объект, а поля и ресурсы, выделение памяти для которых и создание происходит в конструкторе. Дома буду - набросаю пример. -------------------- |
|||
|
||||
| CodeMonkey |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
PsiMagistr, есть хороший пример и я вам в него ткнул:
Как видите, конструктор проводит создание объекта, инициализацию полей и т.п. Если при этом он сталкивается с ошибкой (например, не может открыть файл), он выбрасывает исключение. При этом Delphi автоматически вызывает деструктор. Иными словами, цепочка вызовов при этом выглядит так: CreateInstance (выделение памяти для Self) -> Create -> исключение -> Destroy -> FreeInstance (удаление памяти для Self). Сравните это со штатной ситуацией: CreateInstance (выделение памяти для Self) -> Create, далее вы работаете с объектом, вызывая в конце работы Free, Free -> Destroy -> FreeInstance (удаление памяти для Self). Поскольку в случае возникновения ошибки конструктор выполняется не полностью, то деструктор должен быть готов к удалению частично-инициализированного объекта. Что означает, что не все поля в экземпляре будут заданы. В примере выше обратите внимание, как деструктор закрывает описатель файла только, если он был открыт (if FHandle <> INVALID_HANDLE_VALUE). -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
| PsiMagistr |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
CodeMonkey, благодарю.
Сижу, пробую, что то странное происходит. Но обо всем по порядку. Создал проект. Добавил новый модуль. В новый модуль подключил все заголовочные функции. Подключил сам модуль к модулю формы. Описание класса (раздел interface добавленного модуля.)
Реализация методов класса (Раздел implementation модуля)
Такое впечатление, что мой деструктор очищает не всю память... Это сообщение отредактировал(а) PsiMagistr - 2.6.2010, 15:11 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
||||
|
|||||
| CodeMonkey |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Сыграем в игру (люблю я это дело)
Буратине дали три яблока. Сколько яблок у буратины? Думаете три? Ничего подобного. Никто же не сказал, сколько яблок было до того, как ему дали три. Мораль истории: инициализируйте переменные. Способны ли вы теперь с этой подсказкой найти объяснение видимому поведению? ;) -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
|||
|
||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Благодарю, CodeMonkey. ))) Развивайте мысль. )))) О каких переменных идет речь в данном случае? Насколько я понимаю, все переменные какими мы обладаем вроде получили инициализацию, во всяком случае так считает компилятор.
Внешний указатель вроде только один. MyObject. переменная-поле внутри класса fName. А теперь Ваши соображения? ) -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
| CodeMonkey |
|
||||||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1839 Регистрация: 24.6.2008 Где: Россия, Тверь Репутация: 29 Всего: 89 |
Строка
Раскладывается на более простые действия так: - вызвать конструктор - ссылку, которую вернул конструктор, записать в переменную MyObject. Соответственно, если конструктор возбуждает исключение, то выполнение прерывается и запись чего-либо в MyObject не происходит. Откуда следует, что в MyObject остаётся то, что было в ней до вышеуказанной строчки - т.е. мусор. Очевидно, что вызов
Когда в MyObject лежит мусор, приводит к произвольному поведению. Это может быть нормальная работа, это может быть access violation - что угодно. P.S. Проверка
В деструкторе излишня - этим занимается Free. Уберите. -------------------- Опытный программист на C++ легко решает любые не существующие в Паскале проблемы. |
||||||
|
|||||||
| PsiMagistr |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 479 Регистрация: 31.12.2009 Репутация: 1 Всего: 1 |
Спасибо большое.
Точно. Вызывали мы объект. А он не вызвался (исключение). Что в осталось в указателе? А чушь полная... Неплохо было бы в деструкторе класса прописать чтобы указатель получал хотя бы Nil. Только конечная операция деструктора опять будет inherited Destroy и оно опять мусор зашлет в указатель... Вы пишите If Assigned(self) then в деструкторе лишняя? Вот тут я не могу понять, почему? Да во Free есть эта встроенная проверка. Но именно Free нигде не вызывается. До него дело не доходит, просто. Вызывается голый деструктор. А попытка вызвать Free в деструкторе: self.free; вместо inherited Destroy; просто приведет к тому, что Free сам по себе станет вызывать деструктор, а деструктор - Free. И так без конца. Это сообщение отредактировал(а) PsiMagistr - 3.6.2010, 13:12 -------------------- "Арфы нет? Возьмите бубен! Ребята, будем жить!" (с) "В бой идут одни старики" --- "ИЕ" - один из самых сумасшедших браузеров в нашей галактике. |
|||
|
||||
![]()
|
| Правила форума "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. |