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

Вниз

Исключение в конструкторе   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.013 c
1-59704
Marina_S
2003-05-05 17:02
2003.05.19
как создать avi файлы ?


14-59877
Думкин
2003-04-28 06:47
2003.05.19
Охота на ведьм


14-59849
Ihor Osov'yak
2003-05-01 00:45
2003.05.19
Backdoor.Death.26


9-59519
Landgraph
2002-12-10 17:43
2003.05.19
glNewList(...) ... glEndList();


8-59809
mate
2003-02-08 11:45
2003.05.19
Сохранение рисунка





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский