Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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.53 MB
Время: 0.016 c
1-59734
ultrasuper_asd
2003-05-06 02:09
2003.05.19
как подключить bpl-ку


14-59932
REA
2003-04-28 16:20
2003.05.19
Перебор


1-59672
Patrick
2003-05-07 10:42
2003.05.19
Кодировка клавиш


4-59996
Hawker2007
2003-03-15 17:40
2003.05.19
GetWindowPlacement - ??????


3-59625
AleksandrKu
2003-04-28 16:21
2003.05.19
доступ к Betrive?