316______________________________________________Глава 4

Если пользователь ввел неверное число (например, по ошибке нажал не циф-
ру, а какой-то буквенный символ), то при выполнении функции StrToFloat воз-
никнет исключение класса EConvertError. Соответствующий обработчик исклю-
чения сообщит пользователю о сделанной ошибке и посоветует повторить ввод.
Аналогичная реакция последует на ввод пользователем в качестве делителя нуля
(класс исключения EZeroDivide). Если возникает переполнение, то соответствую-
щий блок catch перехватывает исключение, сообщает о нем пользователю и исп-
равляет ошибку: заносит в результат максимально возможное значение соответст-
вующего знака.

Исключения образуют иерархию, которую вы можете увидеть в главе 15. Бла-
годаря этому можно обрабатывать сразу некоторую совокупность исключений,
производных от одного базового исключения. Для этого надо в заголовке блока
catch указать имя этого базового исключения. Например, исключения EZeroDivi-
de (целочисленное деление на нуль), EOverflow (переполнение при целочисленных
операциях), EInvalidArgument (выход числа за допустимый диапазон) и некото-
рые другие являются производными от класса исключений EMathError. Поэтому
все их можно отлавливать с помощью одного блока catch, например, такого:

catch(EMathErrors)
(
Application->MessageBox("Ошибка вычислений",

"Повторите ввод", МВ_ОК);

)

Правда, в этом случае не конкретизируется причина прерывания исключений.
Однако, такая конкретизация возможна, если воспользоваться свойствами исклю-
чений. Все исключения имеют свойство Message, которое представляет собой стро-
ку, отображаемую пользователю при стандартной обработке исключений.

Чтобы воспользоваться свойствами исключений, надо в заголовке блока catch
не только указать тип исключения, но и создать временный указатель на объект
этого типа. Тогда через имя этого объекта вы получаете доступ к его свойствам.
Ниже приведен пример использования свойств исключений при перехвате искл-'-
чений, наследующих классу EMathError:

catch(EMathError& E)

{                                                                                                                             ;

AnsiString S = "Ошибка вычислений : ";

if(E.Message == "EZeroDivide") S += "деление на нуль";

if(E.Message == "EOverflow") S += "переполнение";

if(E.Message == "EInvalidArgument") S += "недопустимое число";

Application->MessageBox(S.c_str (), "Повторите ввод", МВ_ОК) ;

}

Вводимое в этом операторе имя ссылки на исключение Е носит сугубо лок:'
ный характер и вводится только для того, чтобы можно было сослаться на сво;

во Message по имени объекта исключения.

Как уже говорилось выше, если в заголовке, блока catch указано многото-
то этот блок перехватит любые исключения:

catch (...)
(
ShowMessage("Произошла ошибка.");

)

Блок catch(„.) может сочетаться и с другими блоками catch, но в этом случае
он должен, конечно, располагаться последним. Поскольку этот блок перехвате'
все исключения, то все блоки, следующие за ним, окажутся не доступными
C++Builder следит за этим. Если блок catch(...) оказался не последним, вам будет
выдано компилятором сообщение об ошибке с текстом: «The handler must be \гг.,
(«Обработчик'...' должен быть последним»).