2018-08-02 22:04:49 +03:00
|
|
|
|
<html>
|
|
|
|
|
|
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
|
|
|
|
|
<title></title>
|
|
|
|
|
|
<link rel="StyleSheet" href="../../default.css">
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
<body>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<H1>Обработка исключений: обзор</H1>
|
|
|
|
|
|
<p>Когда во время выполнения программы происходит ошибка,
|
|
|
|
|
|
генерируется так называемое <i>исключение</i>, которое можно <i>перехватить</i>
|
|
|
|
|
|
и <i>обработать</i>. Исключение представляет собой объект класса, производного от
|
|
|
|
|
|
класса <code>Exception</code>, создающийся при
|
|
|
|
|
|
возникновении исключительной ситуации.</p>
|
|
|
|
|
|
<p>Имеется
|
|
|
|
|
|
ряд <a href="StandardExceptions.html">стандартных типов исключений</a>. Можно также
|
|
|
|
|
|
определять <a href="userExceptions.html">пользовательские типы исключений</a>.</p>
|
|
|
|
|
|
<p>Если исключение не обработать, то программа завершится с
|
|
|
|
|
|
ошибкой. Для обработки исключений используется оператор
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<a href="../Operators/try_except.html"><code><b>try</b></code>
|
|
|
|
|
|
... <code><b>except</b></code></a>. </p>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Обычно исключения возбуждаются в подпрограммах, поскольку
|
|
|
|
|
|
разработчик подпрограммы, как правило, не знает, как обработать ошибочную
|
|
|
|
|
|
ситуацию. В месте вызова подпрограммы уже, как правило, известно, каким образом
|
|
|
|
|
|
следует обрабатывать исключение. Например, пусть разработана
|
|
|
|
|
|
следующая функция:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>function</b> mymod(a,b: integer): integer;<br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
Result := a - (a <b>div</b> b) * b;<br>
|
|
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Если вызвать <code>mymod(1,0)</code>, то
|
|
|
|
|
|
будет возбуждено исключение <code>System.DivideByZeroException</code>
|
|
|
|
|
|
целочисленного деления на 0. </p>
|
|
|
|
|
|
<p>Рассмотрим наивную попытку обработать ошибочную ситуацию
|
|
|
|
|
|
внутри функции <code>mymod</code>:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>function</b> mymod(a,b: integer): integer;<br>
|
|
|
|
|
|
<b>begin<br>
|
|
|
|
|
|
</b> <b>if</b> b = 0 <b>then</b> <br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
writeln('Функция mymod: деление на 0');<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
Result := a - (a <b>div</b> b) * b;<br>
|
|
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Подобное решение является плохим, поскольку программист,
|
|
|
|
|
|
разрабатывающий функцию <code>mymod</code>, не знает, как
|
|
|
|
|
|
она будет использоваться. Например, при вызове функции <code>mymod</code>
|
|
|
|
|
|
в цикле мы увидим на экране многократное сообщение об ошибке.</p>
|
|
|
|
|
|
<p>Простейший способ - оставить исходный вариант функции и
|
|
|
|
|
|
обрабатывать исключение <code>System.DivideByZeroException</code>:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>try</b> <br>
|
|
|
|
|
|
readln(a,b);<br>
|
|
|
|
|
|
writeln(mymod(a,b) <b>mod</b> (a-1));<br>
|
|
|
|
|
|
...<br>
|
|
|
|
|
|
<b>except</b><br>
|
|
|
|
|
|
<b>on</b> System.DivideByZeroException <b>do</b><br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
writeln('Деление на 0'); <br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Отличие от вывода внутри функции состоит в том, что при
|
|
|
|
|
|
разработке программы мы сами определяем действие, которое необходимо выполнять
|
|
|
|
|
|
при обработке исключения. Это может быть специфическое сообщение об ошибке,
|
|
|
|
|
|
вывод в файл ошибок или пустой оператор (в случае, когда требуется "беззвучно"
|
|
|
|
|
|
погасить исключение). </p>
|
|
|
|
|
|
<p>Однако, данное решение обладает существенным недостатком:
|
|
|
|
|
|
исключение <code>System.DivideByZeroException</code> будет возбуждено и
|
|
|
|
|
|
при a=1 и не будет связано с функцией <code>mymod</code>.
|
|
|
|
|
|
Для устранения подобного недостатка определим собственный класс исключения и
|
|
|
|
|
|
возбудим его в функции <code>mymod</code>: </p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>type</b> MyModErrorException =<b> class</b>(System.Exception) <b>end</b>;
|
|
|
|
|
|
</code></p>
|
|
|
|
|
|
<p><code><b>function</b> mymod(a,b: integer): integer;<br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
<b>if</b> b = 0 <b>then</b> <br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<b>raise</b> new MyModErrorException('Функция mymod: деление на 0');<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
Result := a - (a <b>div</b> b) * b;<br>
|
|
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Тогда обработка ошибок будет выглядеть так:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>try</b> <br>
|
|
|
|
|
|
readln(a,b);<br>
|
|
|
|
|
|
writeln(mymod(a,b) <b>mod</b> (a-1));<br>
|
|
|
|
|
|
...<br>
|
|
|
|
|
|
<b>except</b><br>
|
|
|
|
|
|
<b>on</b> System.DivideByZeroException <b>do</b><br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
writeln('Деление на 0'); <br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>on</b> e: MyModErrorException <b>do</b><br>
|
|
|
|
|
|
writeln(e.Message);<br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<b>else</b> writeln('какое-то другое исключение') <br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Если сделать <code>MyModErrorException</code>
|
|
|
|
|
|
наследником класса <code>System.ArithmeticException</code>, как и <code>
|
|
|
|
|
|
System.DivideByZeroException</code>, то последний код можно упростить:<code>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
</code></p>
|
|
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>type</b> MyModErrorException =<b> class</b>(System.ArithmeticException) <b>end</b>;</code></p>
|
|
|
|
|
|
<p><code>...</code></p>
|
|
|
|
|
|
<p><code><b>try</b> <br>
|
|
|
|
|
|
readln(a,b);<br>
|
|
|
|
|
|
writeln(mymod(a,b) <b>mod</b> (a-1));<br>
|
|
|
|
|
|
...<br>
|
|
|
|
|
|
<b>except</b><br>
|
|
|
|
|
|
<b>on</b> e: System.ArithmeticException <b>do</b><br>
|
|
|
|
|
|
writeln(e.Message); <br>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<b>else</b> writeln('Какое-то другое исключение') <br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Наконец, можно поступить следующим образом.
|
|
|
|
|
|
Перехватим в функции <code>mymod</code>
|
|
|
|
|
|
исключение <code>System.DivideByZeroException</code> и в
|
|
|
|
|
|
ответ сгенерируем новое - <code>MyModErrorException</code>:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote>
|
|
|
|
|
|
<p><code><b>function</b> mymod(a,b: integer): integer;<br>
|
|
|
|
|
|
<b>begin</b><br>
|
|
|
|
|
|
<b>try</b><br>
|
|
|
|
|
|
|
|
|
|
|
|
Result := a - (a <b>div</b> b) * b;<br>
|
|
|
|
|
|
<b>except</b><br>
|
|
|
|
|
|
<b>on</b> e: System.DivideByZeroException <b>do</b><br>
|
|
|
|
|
|
<b>raise</b>
|
|
|
|
|
|
<b>new</b>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
MyModErrorException('Функция mymod: деление на 0');<br>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<b>end</b>;<br>
|
|
|
|
|
|
<b>end</b>;</code></p>
|
|
|
|
|
|
</blockquote>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
</html>
|