Текущий архив: 2003.05.19;
Скачать: CL | DM;
ВнизИсключение в конструкторе Найти похожие ветки
← →
Top Gun (2003-05-01 15:37) [0]У меня в конструкторе некоего класса есть такой код:
if Handle=0 then raise TWindowExeption.create;
Описание класса TWindowExeption:
type
TWindowExeption=class
constructor Create;
end;
...
constructor TWindowExeption.Create;
begin
messagebox(0,"Невозможно создать окно","Невозможно создать новое окно",MB_OK);
end;
Когда возбуждается исключение, то текст messagebox"а появляется на экране, но потом почему-то идет Runtime Error. Отчего так ?
← →
vuk (2003-05-01 15:46) [1]1. По соглащению все классы являются наследниками от класса Exception.
2.За отображение сообщений отвечает не класс исключения а корневой обработчик исключений. Исключению же просто задается в конструкторе сообщение, которое этот корневой обработчик выводит. В вашем случае в будет правильнее сделать так:
type
EWindowException = class(Exception);
....
if Handle = 0 then
raise EWindowException.Create( "Невозможно создать новое окно" );
Обратите внимсание на именование классов.
← →
Top Gun (2003-05-03 18:32) [2]1. У меня не подключен модуль Classes
2. А почему у меня Runtime Error выскакивал то ?
← →
Юрий Зотов (2003-05-03 19:27) [3]Оператор raise не только вызывает исключение, но и приводит к его специальной обработке. В частности, после вызова конструктора (в котором вполне успешно показывается Ваше соообщение - а почему бы ему не показываться?) компилятор строит код, в котором делается попытка показать стандартное сообщение об ошибке. При этом через сответствующие свойства идет обращение к полям FMessage и/или FHelpContext объекта-исключения (предполагается, что программист следует стандарту и породил этот объект от Exception). А у Вашего объекта этих полей нет - вот и возникает ошибка.
Вообще, при работе с объектами-исключениями компилятор строит довольно хитрый специальный код, поэтому вряд ли стоит его обманывать и подменять эти объекты другими. Следуйте стандарту, наследуйте свое исключение от Exception и не будет никаких проблем. Какие есть причины для иного?
Кстати, модуль Classes здесь ни при чем - класс Exception содержится в SysUtils.
← →
Набережных С. (2003-05-03 22:10) [4]>Top Gun (01.05.03 15:37)
Чтобы делать такие вещи, нужно сначала более-менее разобраться с механикой обработки исключений в Delphi. Ты сгенерил исключение и его не обработал - почему же тебя удивляет появление Runtime Error? Все необработанные сообщения попадают либо в Application.HandleException, либо, при отсутствии Application, в обработчик по умолчанию(есть еще варианты, но не суть важно). HandleException выглядит так:
if ExceptObject is Exception then
begin
if not (ExceptObject is EAbort) then
if Assigned(FOnException) then
FOnException(Sender, Exception(ExceptObject))
else
ShowException(Exception(ExceptObject));
end else
SysUtils.ShowException(ExceptObject, ExceptAddr);
Обработка по умолчанию несколько разная в разных версиях, но все равно мы попадаем в _Halt0, которая так или иначе либо пишет в выходной буфер(консольное приложение), либо выводит сообщение.
Как видишь, все вполне логично.
P.S. Такие приемы стоит использовать при реальной необходимости, четко осознавая свои действия. В подавляющем большинстве случаев прекрасно подходит стандартный способ(см. Юрий Зотов © (03.05.03 19:27))
← →
Top Gun (2003-05-03 22:54) [5]Прошу прощения, Exception определен, конечно, в SysUtils, но он у меня и не подключен как раз (все делаю на WinApi - очень важен размер приложения)...
Давайте переформулирую вопрос по другому - а как грамотно сделать класс, который можно вызвать по Raise ESomeClass ?
Или по другому - как сделать, чтобы не вываливалось это самое Runtime Error ? SysUtils подключать не могу...
← →
circul (2003-05-03 23:10) [6]1. Можно переопределить класс Exception
2. А зачем возбуждать исключение? Из кода видно, что класс Exception служит только для выдачи сообщения.
Почему просто не воспользоваться MessageBox ?
← →
vuk (2003-05-04 01:59) [7]to Top Gun:
>все делаю на WinApi - очень важен размер приложения
Неужели несчастные 30 килобайт так подпортят жизнь? И если да, то что Вы такое пишете?
>как грамотно сделать класс, который можно вызвать по Raise
>ESomeClass ?
Класс может быть абсолютно произвольным, дело не в нем, а в самой подсистеме обработке исключений, которая как раз и реализована в модуле sysutils. Вот как раз без этой подсистемы и получаем то самое Runtime Error. Если очень хочется, можете самостоятельно реализовать такую подсистему. Только стоит ли геморрой свеч?
to circul:
1. Если используется стандартный механизм обработки исключений(из sysutils.pas), то не очень-то. :o)
2. Класс exception используется не для выдачи сообщений, а для передачи информации об исключении. Выдача сообщения происходит только тогда, когда исключение не обработано и управление попадает в этот корневой обработчик. Но ведь может же и не попасть. Оно может быть перехвачено и корректно обработано. А что Вы будете делать с MessageBox, если Вам не нужно выдавать никаких сообщений?
← →
Top Gun (2003-05-04 12:39) [8]Я здесь использую исключение, чтобы прервать конструктор, чтобы объект не создавался
Просто где-то здесь приводили пример класса без наследования от Exeption, что его можно вызвать по raise !
← →
Набережных С. (2003-05-04 16:03) [9]Извини, но рано тебе этим заниматься, ей-богу.
← →
Top Gun (2003-05-05 13:48) [10]Набережных С., спасибо за грамотное объяснение по теме ! Уважаю !
Всем остальным:
может объяснит кто-нибудь ?
как грамотно сделать класс, который можно вызвать по Raise ESomeClass
Я где-то здесь видел такой пример ! Причем достаточно простой. Там еще Юрий Зотов сказал, что если не хочется использовать SysUtils - можно делать так !
← →
vuk (2003-05-05 13:52) [11]to Top Gun:
>как грамотно сделать класс, который можно вызвать по Raise
>ESomeClass
Повторяю еще раз. Класс может быть любой. Хоть TObject.
← →
Набережных С. (2003-05-05 19:02) [12]>All
Если у кого-то случайно сохранилась та ветка, то будьте добры, вышлите ее ему.
>Top Gun (05.05.03 13:48)
Пожалуйста. Но я не собираюсь тебе заново писать то, что было здесь совсем недавно, тем более, что меня же там и обвинили неизвестно в чем. Может, кто вышлет. Боюсь только, что толку с этого не будет. Здесь важно понять принцип, а не копировать бездумно элементарные примеры. Реализация же напрямую зависит от конкретных условий.
← →
Top Gun (2003-05-05 20:23) [13]>Повторяю еще раз. Класс может быть любой. Хоть TObject
Да, но я привел пример с TWindowExeption ! У меня там ошибка !
Я имел в виду
как грамотно сделать класс, который можно вызвать по Raise ESomeClass , чтобы он отработал без ошибок !
Набережных С., ну если не сложно - приведи пример еще раз ! Насколько помню - там было тоже, что и у меня ! Значит, твой класс тоже бы выводил ошибку. Никаких полей FMessage там не было !
← →
Набережных С. (2003-05-05 21:17) [14]Блин, да не в классе же дело-то, vuk совершенно правильно сказал! Было там поле FMsg, но это не имеет никакого значения! Если ты пропустишь исключение в обработчик по умолчанию, то будет сформировано и выдано то самое Runtime error 217 at ... Не хочешь, чтобы что-то выводилось - не выводи и не выпускай исключение. Если тебе нужно просто прервать конструктор, то сделай примерно так:
TWindowExeption = class
public
constructor Create(AMsg: string);
Msg: string;
end;
constructor TWindowExeption.Create(AMsg: string);
begin
Msg:=AMsg;
end;
constructor TMyObject.Create;
begin
raise TWindowExeption.Create("Хрен вам!");
end
А создавай так:
try
MyObject:=TMyObject.Create;
except
on E: TWindowExeption do;
else raise;
end;
или так:
try
MyObject:=TMyObject.Create;
except
on E: TWindowExeption do ShowMessage(E.Msg);
else raise;
end;
← →
Top Gun (2003-05-05 23:37) [15]А, все понятно.
А можно сделать так, создаешь класс типа MyClass:=TMyClass.Create
И если конструктору что-то не понравилось - то жизнь объекта прекращается, и в качестве ссылки передается nil, то есть MyClass становится равным nil ?
Мне исключения нужны-то только для того, чтобы прервать создание объекта, может еще как это сделать можно, чтобы без конструкции try...except все было ок ?!
← →
Top Gun (2003-05-06 18:17) [16]up
← →
jack128 (2003-05-06 19:23) [17]Top Gun (05.05.03 23:37)
try
MyClass:=TMyClass.Create;
except
MyClass := nil;
end; и без try except end; никак.
← →
app (2003-05-06 19:30) [18]Top Gun (06.05.03 18:17)
Ты когда прекратишь создавать пустые сообщения, смотри придется делать всем твоим сообщения down и не удивляйся потом, больще предупреждать не буду.
← →
Top Gun (2003-05-06 19:59) [19]Точно никак ? Ну смотрите, ведь при исключении дельфи уничтожет класс, а как бы эмулировать ее действия ? Ведь наверняка можно ?
← →
Top Gun (2003-05-06 20:00) [20]app, так вот видишь, мне jack128 ответил !!! А так бы не ответил
← →
app (2003-05-06 20:01) [21]Ну давай и дальше так
← →
Набережных С. (2003-05-06 20:17) [22]Не усложняй себе жизнь. Если и можно, то, думаю, весьма не просто и не универсально. Впрочем, я никогда не пробовал. Куда проще объявить class function, возвращающую экземпляр, в которой совершенно спокойно вызывать конструктор и деструктор. Еще лучше ИМХО - объявить интерфейс и опубликовать функцию, его возвращающую. А сам класс спрятать. Конструктор ДОЛЖЕН вернуть объект - таков смысл его существования.
Страницы: 1 вся ветка
Текущий архив: 2003.05.19;
Скачать: CL | DM;
Память: 0.5 MB
Время: 0.006 c