Классы исключительных ситуаций именуются начиная с буквы "Е", а базовый класс просто называется Exception. Этот базовый класс содержит необходимую функциональность, которую наследуют все объекты ошибок. Тут можно выделить свойство Message, в котором содержится сообщение об ошибке и функции работы с файлом помощи, через которые можно вызвать файл справки с описанием произошедшей ошибки.
В библиотеке VCL предопределено достаточно большое количество классов на различные типы ошибок, и все они являются наследниками Exception. Например, класс EinOutError соответствует ошибке ввода-вывода. Такие ошибки возникают при обращении к дискам.
Когда происходит ошибка, то создается объект, который является наследником класса, соответствующего типу ошибке. Так, если произошла ошибка ввода- вывода, то будет создан экземпляр класса EinOutError.
Давайте рассмотрим пример из листинга 8.10, где в блоке обработки ошибок я пытаюсь разделить число на ноль, что запрещено. Результат деления заносится в переменную t. Обратите внимание, что после этого я делаю проверку if. Эта проверка абсолютно бессмысленна и добавлена только для того, чтобы после деления было хоть какое-то обращение к переменной. Если никакого обращения не будет, то Delphi видит бессмысленность деления и оптимизатор не делает его.
var
t,r:Double; begin try r: =0; t:=10/r; if t>0 then exit; except
// обработка ошибки ввода-вывода
on EinOutError do begin
ShowMessage('Ошибочка ввода-вывода'); end;
// обработка деления на ноль
on е:
EZeroDivide do begin .
ShoWMessage('Ну нельзя делить на ноль :: '+е.Message); end; // Иначе else
ShowMessage('Не понял в чем дело, но что-то произошло');
end;
end;
В данном случае в блоке except идет два блока обработки разных типов ошибок. Чтобы проверить, не произошла ли ошибка ввода-вывода, пишем следующий блок:
on [переменная : ] класс_ошибки do begin
// Ошибка ввода-вывода end;
Если дословно перевести, что здесь написано, то это будет выглядеть так: в случае ошибки выполнить код между begin и end. Обратите внимание, что переменную я заключил в квадратные скобки. Это означает, что переменную заводить не обязательно, что мы и делаем при обработке ошибки ввода-вывода:
on EInOutError do begin
Shovfllessage('Ошибочка ввода-вывода'); end;
В случае ошибки вызывается функция showMessage, которая отображает на экране окно диалога с сообщением, которое указано в качестве параметра.
А теперь посмотрим на то, как мы обрабатываем ошибку деления на ноль:
on е:EZeroDivide do begin
ShowMessage('Ну нельзя делить на ноль :: '+е.Message); end;
Ошибке деления на ноль соответствует класс EZeroDivide. Перед классом ошибки написана переменная с именем е. Через нее мы сможем узнать сообщение об ошибке, например, так е.Message.
Помимо этого, в блоке except листинга 8.10 стоит еще ключевое слово else, как при логической операции. Обратите внимание, что после end прямо перед else стоит точка с запятой, хотя мы знаем, что это ее не нужно ставить. Ненужно только для логических операций. В данном случае else используется для обработки исключительных ситуаций, и операция после этого ключевого слова будет выполнена, если до этого ошибка не была обработана. То есть если произошла ошибка, которая не была обработана блоком on ошибка do, то будет выполнен код после else.
Итак, попробуйте создать новое приложение, поместить на него кнопку и по ее нажатии написать код из листинга 8.10. Запустите пример и лучше сделайте это из Delphi. Теперь попробуйте нажать на кнопку. Произойдет ошибка, и Delphi перехватит на себя управление, покажет строку кода, где произошла исключительная ситуация, и покажет окно диалога с сообщением, описывающим ошибку.
Осмотрев строку кода, где произошла ошибка, нажимаем клавишу <F9>, чтобы продолжить выполнение программы. И в этот момент управление будет передано нашей программе, и вы увидите сообщение, которое мы показываем с помощью функции ShowMessage В блоке except.
Если бы вы запустили программу не из Delphi, а из файлового менеджера активировали исполняемый файл, созданный в Delphi, то в момент ошибки вы увидели бы только второе сообщение, которое мы отображаем с помощью функции SenMessage.
Сообщения могут генерироваться не только исполняемой средой, но и вручную. Чтобы сгенерировать свое сообщение, используется оператор raise. После этого оператора нужно указать объект ошибки. Именно объект, т. е экземпляр какого-то класса ошибки.
Давайте посмотрим, как можно вручную сгенерировать ошибку ввода-вывода. Чтобы создать новый объект этого класса, нужно вызвать метод create, а этому методу передается сообщение, которое будет отображаться, когда сработает событие.
Итак, конструктор create вернет нам экземпляр класса ошибки ввода-вывода. Его мы и должны указать после оператора raise:
Вы можете создать собственный класс ошибки, нарастить его возможности, как душа пожелает, и использовать его. Давайте посмотрим, как это будет выглядеть на примере. Создадим класс MyException, который будет является наследником базового класса всех ошибок — Exception:
type
MyException = class(Exception) public
function GetSomeStrO:String;
end;
Это объявление типа, поэтому все это должно быть в разделе type вашего модуля. Помимо того что класс наследовал от базового, мы объявили еще одну функцию Getsomestr, которая просто возвращает строку. Не будем усложнять жизнь, а реализуем эту функцию банально — просто вернем заранее определенную строку:
function MyException.GetSomeStr: String;
begin
Result:='Это моя строка';
end;
Теперь поместите на форму кнопку и по ее нажатии напишите следующий код: try
raise MyException.Create('Тест'); except on e:MyException do
begin
ShowMessage(e.GetSomeStr);
end;
end;
В разделе try мы вручную генерируем ошибку собственного типа MyException. В разделе except мы перехватываем эту ошибку и с помощью функции ShowMessage отображаем результат функции GetSomeStr. Вот так все просто и красиво.
