Java: Операторы throw и throws. Повторное генерирование исключений

В программировании часто возникают ситуации, когда программисту необходимо самому инициировать генерацию исключения для указания, напри­мер, на заведомо ошибочный результат выполнения операции, на некорректные значения параметра метода и др. Исключительную ситуацию можно создать с помощью оператора throw , если объект-исключение уже существует, или инициализировать его прямо после этого оператора. Оператор throw используется для генерации исключения. Для этого может быть использован объект класса Throwable или объект его подкласса, а также ссылки на них. Общая форма записи инструкции throw , генерирующей исключение:

throw объектThrowable;

Объект-исключение может уже существовать или создаваться с помощью оператора new :

t hrow new IOException () ;

При достижении оператора throw выполнение кода прекращается. Ближайший блок try проверяется на наличие соответствующего обработчика catch . Если он существует, управление передается ему, иначе проверяется следующий из вложенных операторов try . Инициализация объекта-исключения без оператора throw никакой исключительной ситуации не вызовет.

Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw генерирует исключение, обрабатываемое в разделе catch ,
в котором генерируется другое исключение.

/* пример # 3: генерация исключений: ThrowGeneration . java */

package chapt08;

import java.io.File;

public class ThrowGeneration {

public static void connectFile(File file) {

if (file == null || !file.exists())

throw new IllegalArgumentException();/* генерация

исключения */

//

public static void main(String args) {

File f = new File("demo.txt");

// File f = null;

connectFile (f);

} catch (IllegalArgumentException e) {

System.err .print("обработка unchecked-"

+ " исключения вне метода: " + e);

Вызываемый метод connectFile () может (при отсутствии файла на диске или при аргументе null ) генерировать исключение, перехватываемое обработчиком. В результате этого объект непроверяемого исключения IllegalArgument Exception , как подкласса классаRuntime Exception , передается обработчику исключений в методе main() .

В случае генерации проверяемого исключения компилятор требует обра­ботки исключения в методе или отказа от нее с помощью инструкции throw s .

Если метод генерирует исключение с помощью оператора throw и при этом блок catch в методе отсутствует, то для передачи обработки исключения вызывающему методу тип проверяемого (checked) класса исключений должен быть указан в операторе throws при объявлении метода. Для исключений, являющихся подклассами класса RuntimeException (unchecked) и используемых для отображения программных ошибок, при выполнении приложения throws в объявлении должен отсутствовать.

В данной статье рассматривается используемый в Java механизм обработки исключений. Исключение в Java - это объект, который описывает исключительное состояние, возникшее в каком-либо участке программного кода. Когда возникает исключительное состояние, создается объект класса Exception . Этот объект пересылается в метод, обрабатывающий данный тип исключительной ситуации. Исключения могут возбуждаться и для того, чтобы сообщить о некоторых нештатных ситуациях.

Ключевые слова исключений try, catch, throw, throws, finally

Механизм исключительных ситуаций в Java поддерживается пятью ключевыми словами:

  • catch,
  • throw,
  • throws,
  • finally.

Ниже приведена общая форма блока обработки исключений.

Try { // блок кода } catch ( е) { // обработчик исключений типа ExceptionType1 } catch ( е) { // обработчик исключений типа ExceptionType2 } finally { // ... }

Типы исключений

В вершине иерархии исключений стоит класс Throwable , который наследуется от Object . Каждый из типов исключений является подклассом Throwable. Два непосредственных наследника класса Throwable делят иерархию подклассов исключений на две различные ветви. Иерархия классов представлена на рисунке.

Класс Ехception используется для описания исключительных ситуации, которые должны перехватываться программным кодом пользователя. Класс Error предназначен для описания исключительных ситуаций, которые при обычных условиях не должны перехватываться в пользовательской программе.

Неперехваченные исключения

Объекты-исключения автоматически создаются исполняющей средой Java в результате возникновения определенных исключительных ситуаций. Пример программы, в которой создаем исключительную ситуацию при делении на нуль.

Package samples; class TestException { public static void main(String args) { int d = 0; int a = 42 / d; System.out.println ("a = " + a); } }

В консоль будет выведено следующее сообщение.

Exception in thread "main" java.lang.ArithmeticException: / by zero at samples.TestException.main(TestException.java:8)

Следует обратить внимание на тот факт, что типом возбужденного исключения был не Exception и не Throwable . Это подкласс класса Exception , а именно: ArithmeticException , поясняющий, какая ошибка возникла при выполнении программы.

Изменим класс добавлением статического метода subroutine , в котором создадим такую же исключительную ситуацию.

Package samples; public class TestException { static void subroutine() { int d = 0; int a = 10 / d; System.out.println ("a = " + a); } public static void main(String args) { TestException.subroutine(); } }

Сообщение выполнения программы показывает, как обработчик исключений исполняющей системы Java выводит содержимое всего стека вызовов.

Exception in thread "main" java.lang.ArithmeticException: / by zero at samples.TestException.subroutine(TestException.java:8) at samples.TestException.main(TestException.java:14)

Перехват исключений try/catch

Для защиты программного кода от исключений необходимо использовать связанные блоки с ключевыми словами try catch ; catch помещается сразу же после try-блока. В блоке catch задается тип исключения, которое необходимо обработать.

Class TestException { public static void main(String args) { try { int d = 0; int a = 42 / d; } catch (ArithmeticException e) { System.out.println("division by zero"); } } }

Целью большинства хорошо сконструированных catch -разделов должна быть обработка возникшей исключительной ситуации и приведение переменных программы в некоторое разумное состояние - такое, чтобы программу можно было продолжить так, будто никакой ошибки и не было (в нашем примере выводится предупреждение - division by zero).

Несколько разделов catch

В отдельных случаях блок программного кода может вызвать исключения различных типов. Для того, чтобы локализовать обработку подобных ситуаций, можно использовать несколько catch -разделов для одного try-блока . Блоки наиболее специализированных классов исключений должны идти первыми, поскольку ни один подкласс не будет достигнут, если поставить его после суперкласса.

В следующем примере перехватывается два различных типа исключений, причем за этими двумя специализированными обработчиками следует раздел catch общего назначения, перехватывающий все подклассы класса Throwable .

Class MultiCatch { static int c = { 1 }; public static void main(String args) { try { int a = args.length; System.out.println("a = " + String.valueOf(a)); int b = 23 / a; c = 33; } catch (ArithmeticException e) { System.out.println("ArithmeticException: " + e.getMessage()); } catch(ArrayIndexOutOfBoundsException e) { System.out.println("ArrayIndexOutOfBoundsException: " + e.getMessage()); } } }

Данный пример, запущенный без параметров, вызывает возбуждение исключительной ситуации деления на нуль. Если в командной строке будет определен один или несколько параметров, тем самым установив "а" в значение больше нуля, то будет возбуждено исключение выхода индекса за границы массива ArrayIndexOutOfBounds . Ниже приведены результаты работы этой программы, запущенной и тем и другим способом.

А = 0 div by 0: java.lang.ArithmeticException: / by zero a = 1 array index oob: java.lang.ArrayIndexOutOfBoundsException:33

Вложенные операторы try

Операторы try можно вкладывать друг в друга. Если у оператора try низкого уровня нет раздела catch , соответствующего возбужденному исключению, стек будет развернут на одну ступень выше, и в поисках подходящего обработчика будут проверены разделы catch внешнего оператора try. Пример вложения двух операторов try catch друг в друга посредством вызова метода.

Class MultiNest { static int c = { 1 }; static void checkArray() { try { c = 33; } catch(ArrayIndexOutOfBoundsException e) { System.out.println "ArrayIndexOutOfBoundsException: " + e.getMessage()); } } public static void main(String args) { try { int a = args.length(); System.out.println("a = " + a); int b = 23 / a; checkArray(); } catch (ArithmeticException e) { System.out.println("ArithmeticException: " + e.getMessage()); } } }

Возбуждение исключений throw

Программа может явно вызывать исключение, используя оператор throw . После выполнения оператора throw процесс выполнения программы приостанавливается и последующие операторы не выполняются. JVM просматривает ближайший блоки try ... catch , соответствующий типу исключения, для "передачи управления". Если подходящий блок не будет найден, то обработчик исключений остановит программу и "распечатает" при этом состояние стека вызовов.

Пример исключения, в котором сначала создается объект-исключение, затем оператор throw возбуждает исключительную ситуацию, после чего то же исключение возбуждается повторно - на этот раз уже кодом перехватившего его в первый раз раздела catch .

Class TestThrow { static void method() { try { throw new NullPointerException("Exception in method"); } catch (NullPointerException e) { System.out.println(e.getMessage()); throw e; } } public static void main(String args) { try { method(); } catch(NullPointerException e) { System.out.println("Catch inside main: " + e.getMessage()); } } }

Результат выполнения программы приведен ниже.

Exception in method Catch inside main: Exception in method

Объявление об исключении throws

Если метод может возбуждать исключения, которые сам не обрабатывает, то он должен объявить об этом, чтобы вызывающие его другие методы могли защитить себя от этих исключений. Для задания списка исключений, которые могут возбуждаться методом, используется ключевое слово throws .

Если метод в явном виде (т.е. с помощью оператора throw ) возбуждает исключение, тип класса исключений должен быть указан в операторе throws в объявлении этого метода. Принимая данное положение во внимание синтаксис определения метода должен быть описан следующим образом:

Public class TestThrow { static void method() throws IllegalAccessException { try { System.out.println("inside method"); throw new IllegalAccessException ("Exception in method"); } catch (NullPointerException e) { System.out.println(e.getMessage()); } } public static void main(String args) { try { method(); } catch(IllegalAccessException e) { System.out.println("Catch inside main: " + e.getMessage()); } } }

Результат работы примера:

Inside method Catch inside main: Exception in method

Ключевое слово finally

В случае, когда необходимо гарантировано выполнить определенный участок кода необходимо использовать ключевое слово finally . Использование связи try...finally позволяет обеспечить выполнение кода независимо от того, какие исключения были возбуждены и перехвачены, даже в тех случаях, когда в методе нет соответствующего возбужденному исключению раздела catch.

У каждого раздела try должен быть по крайней мере или один раздел catch или блок finally . Блок finally очень удобен для закрытия файлов и освобождения любых других ресурсов, захваченных для временного использования в начале выполнения метода.

Ниже приведен пример класса с двумя методами, завершение которых происходит по разным причинам, но в обоих перед выходом выполняется код раздела finally .

Public class TestFinally { static void methodA() { try { System.out.println("inside methodA"); throw new RuntimeException("Exception in methodA"); } finally { System.out.println("finally inside methodA"); } } static void methodB() { try { System.out.println("inside methodB"); return; } finally { System.out.println("finally inside methodB"); } } public static void main(String args) { try { methodA(); } catch (Exception e) { System.out.println("Catch exception iinside main"); } methodB(); } }

В тестовом примере в методе methodA возбуждается исключение. Но перед преждевременным выходом из блока try , выполняется раздел finally . Во втором методе methodB завершается работа в try -блоке оператором return , но и при этом перед выходом из метода выполняется программный код блока finally . Результат работы тестового примера:

Inside methodA finally inside methodA Catch exception iinside main inside methodB finally inside methodB

Обработка исключений в Java предоставляет исключительно мощный механизм для управления сложными программами. Ключевые слова try, throw, catch позволяют выполнять обработку ошибок и разных нештатных ситуаций в программе.

Наследование исключений

catch - полиморфная конструкция, т.е. catch по типу parent перехватывает исключения любого типа, которые является Parent"ом.

Public class TestException { public static void main(String args) { try { System.err.print("level 0"); throw new RuntimeException(); System.err.print("level 1"); } catch (Exception e) { // catch Exception ПЕРЕХВАТ RuntimeException System.err.print("level 2"); } System.err.println("level 3"); } }

В результате в консоли увидим

Level 0 level 2 level 3

Error и Exception из параллельных веток наследования от Throwable , поэтому catch по одному «брату» не может поймать другого «брата».

Public class TestError { public static void main(String args) { try { System.err.println("level 0"); if (true) { throw new Error(); } System.err.println("level 1"); } catch (Exception e) { System.err.println("level 2"); } System.err.println("level 3"); } }

Результат выполения программы

Level 0 Exception in thread "main" java.lang.Error at TestError.main(TestFinally.java:8)

Множественные исключения

Объявление исключений в методе может быть множественным. Пример:

Import java.io.EOFException; import java.io.FileNotFoundException; public class MultiException { // объявляем исключения public static void main(String args) throws EOFException, FileNotFoundException { if (System.currentTimeMillis() % 2 == 0) { throw new EOFException(); } else { throw new FileNotFoundException(); } } }

Обработка исключений строится на использовании трех ключевых слов: try , catch и throw . Сначала рассмотрим этот процесс в самых общих чертах. Операторы программы, предназначенные для управления исключениями, содержатся в блоке try. Если исключение (т.е. ошибка) возникает в блоке try, происходит его "выброс" (с помощью оператора throw). "Выброшенное" исключение подхватывается (вернее, перехватывается) с помощью оператора catch и затем обрабатывается. А теперь более детально.

Как отмечено выше, любой оператор, который генерирует исключение, должен выполняться внутри блока try. (Функции, вызываемые из блока try, также могут генерировать исключения.) Любое исключение должно быть перехвачено оператором catch, который располагается сразу после оператора try, сгенерировавшего исключение. Общая форма записи блоков try и catch имеет следующий вид.

Try{ //блок_trу } catch (тип1 arg ) { //блок_саtch_l } catch (тип2 arg ) { //блок_catch_2 } catch (типЗ arg ) { //блок_сatch_3 } // . . . catch (типN arg ) { //блок_catch_N }

Блок try должен содержать ту часть программы, которая предназначена для обработки ошибок. Она может быть совсем небольшой и состоять всего из нескольких операторов, принадлежащих одной функции, или настолько всеобъемлющей, что в блок try будет помещено тело функции main()(в этом случае будет эффективно обрабатываться вся программа).

После генерации исключение перехватывается соответствующим оператором catch , который и обрабатывает это исключение. С блоком try может быть связан не один, а несколько операторов catch. Какой из них использовать, определяется типом исключения, т.е. если тип данных, заданный оператором catch, совпадает с типом исключения, именно этот оператор catch выполняется(а все другие опускаются). При перехвате исключения аргумент arg получает некоторое значение. В перехвате могут участвовать данные любого типа, в том числе классы, создаваемые программистом. Если не сгенерировано ни одно исключение(т.е. если внутри блока try не обнаружилось ни одной ошибки), то не выполнится ни один оператор catch.

Оператор throw генерирует исключение. Вот как выглядит общая форма оператора throw,

Throw исключение ;

Оператор throw должен выполняться либо из самого блока try, либо из любой функции, вызываемой(прямо или косвенно) из блока try. Элемент исключение представляет собой "выбрасываемое" в этот критический момент значение.

Если программа сгенерирует исключение, для которого не найдется соответствующего оператора catch, может произойти аварийное завершение программы. При генерации необработанных исключений будет вызвана функция terminate(). По умолчанию функция terminate() вызывает функцию abort(), предназначенную для останова программы. Однако, используя функцию set_terminate(), можно указать свои обработчики таких ситуаций.

Пример

#include using namespace std; int main() { cout << "Начало\n"; try { // начало блока try cout << "Внутри блока try\n"; throw 100; // генерируем ошибку cout << "Этот оператор выполнен не будет"; } catch (int i) { // перехватываем ошибку cout << "Перехватываем исключение - "; cout << "значение равно: "; cout << i << "\n"; } cout << "Конец"; return 0; }

При выполнении этой программы будут выведены следующие сообщения.

Начало Внутри блока try Перехватываем исключение - значение равно: 100 Конец

Как видите, в программе присутствует блок try, содержащий три оператора, и оператор catch (int i), который обрабатывает исключения целого типа. Внутри блока try будут выполнены только два из трех операторов: первый (из двух) оператор cout и оператор throw. Как только будет сгенерировано исключение, управление сразу перейдет к выражению catch и блок try прекратит свою работу, т.е. оператор catch не вызывается: просто ему передается управление программой. (Для реализации этой передачи стек программы автоматически устанавливается должным образом.) Значит, оператор cout, следующий за оператором throw, никогда не будет выполнен.

Операторы throw и finally

Оператор throw

Исключение может быть сгенерировано вручную с помощью оператора throw . Ниже приведена общая форма такого генерирования:

throw exceptOb;

где в качестве exceptOb должен быть обозначен объект класса исключений, производного от класса Exception. Ниже приведен пример программы, в которой демонстрируется применение оператора throw для генерирования исключения OverflowException:

Using System; namespace ConsoleApplication1 { class Program { static void Main() { int i = int.Parse(Console.ReadLine()); byte j; try { if (i > 255) // Генерируем исключение throw new OverflowException(); else j = (byte)i; } catch (OverflowException) { Console.WriteLine("Возникло переполнение"); } Console.ReadLine(); } } }

Обратите внимание на то, что исключение OverflowException было сгенерировано с использованием ключевого слова new в операторе throw. Не следует забывать, что в данном случае генерируется конкретный объект, а следовательно, он должен быть создан перед генерированием исключения. Это означает, что сгенерировать исключение только по его типу нельзя. В данном примере для создания объекта OverflowException был автоматически вызван конструктор, используемый по умолчанию, хотя для генерирования исключений доступны и другие конструкторы.

Повторное генерирование исключений

Исключение, перехваченное в одном блоке catch, может быть повторно сгенерировано в другом блоке, чтобы быть перехваченным во внешнем блоке catch. Наиболее вероятной причиной для повторного генерирования исключения служит предоставление доступа к исключению нескольким обработчикам. Допустим, что один обработчик оперирует каким-нибудь одним аспектом исключения, а другой обработчик - другим его аспектом. Для повторного генерирования исключения достаточно указать оператор throw без сопутствующего выражения, как в приведенной ниже форме:

Не следует, однако, забывать, что когда исключение генерируется повторно, то оно не перехватывается снова тем же самым блоком catch, а передается во внешний блок catch. Пример:

Using System; namespace ConsoleApplication1 { class Program { static void Del(int x, int y) { try { int result = x / y; } catch(DivideByZeroException) { Console.WriteLine("Деление на ноль!"); throw; } } static void Main() { try { Del(5, 0); } catch (DivideByZeroException) { Console.WriteLine("Программная ошибка!"); } Console.ReadLine(); } } }

Как видите, исключение DivideByZeroException обрабатывается как во внутреннем блоке, так и во внешнем.

Использование блока finally

Иногда требуется определить кодовый блок, который будет выполняться после выхода из блока try/catch. В частности, исключительная ситуация может возникнуть в связи с ошибкой, приводящей к преждевременному возврату из текущего метода. Но в этом методе мог быть открыт файл, который нужно закрыть, или же установлено сетевое соединение, требующее разрывания. Подобные ситуации нередки в программировании, и поэтому для их разрешения в C# предусмотрен удобный способ: воспользоваться блоком finally .

Использование блока finally гарантирует, что некоторый набор операторов будет выполняться всегда, независимо от того, возникло исключение (любого типа) или нет.

Для того чтобы указать кодовый блок, который должен выполняться после блока try/catch, достаточно вставить блок finally в конце последовательности операторов try/catch. Ниже приведена общая форма совместного использования блоков try/catch и finally:

try { // Блок кода, предназначенный для обработки ошибок. } catch (ExcepTypel exOb) { // Обработчик исключения типа ExcepTypel } catch (ExcepType2 exOb) { // Обработчик исключения типа ЕхсерType2. } finally { // Код завершения обработки исключений. }

Блок finally будет выполняться всякий раз, когда происходит выход из блока try/catch, независимо от причин, которые к этому привели. Это означает, что если блок try завершается нормально или по причине исключения, то последним выполняется код, определяемый в блоке finally. Блок finally выполняется и в том случае, если любой код в блоке try или в связанных с ним блоках catch приводит к возврату из метода.

Введение

Язык С представляет программисту очень ограниченные возможности обработки исключений, возникших при работе программы. В этом отношении С++ намного развитее С. Здесь у программиста существенно большие возможности по непосредственной обработке исключений. Комитет по разработке стандартов С++ предоставил очень простую, но мощную форму обработки исключений.

Темные дни С

Типичная функция, написанная на С, выглядит примерно так:

Long DoSomething() { long *a, c; FILE *b; a = malloc(sizeof(long) * 10); if (a == NULL) return 1; b = fopen("something.bah", "rb"); if (b == NULL) { free(a); return 2; } fread(a, sizeof(long), 10, b); if (a != 0x10) { free(a); fclose(b); return 3; } fclose(b); c = a; free(a); return c; }

Выглядит не очень, не так ли? Вы целиком и полностью зависите от значений, которые возвращают вам функции и для каждой ошибки вам постоянно нужен код, который ее обрабатывает. Если вы, скажем, в функции работаете хотя бы с 10 указателями (рапределяете память, освобождаете ее и т.д.), то наверняка половину кода функции будет занимать код обработки ошибок. Такая же ситуация будет в коде, вызывающем эту функцию, так как здесь также нужно обработать все возвращаемые коды ошибок.

Try-catch-throw

Давайте же разберем основы обработки исключений в С++. Чтобы комфортно работать с исключениями в С++ вам нужно знать лишь три ключевых слова:

  • try (пытаться) - начало блока исключений;
  • catch (поймать) - начало блока, "ловящего" исключение;
  • throw (бросить) - ключевое слово, "создающее" ("возбуждающее") исключение.

А теперь пример, демонстрирующий, как применить то, что вы узнали:

Void func() { try { throw 1; } catch(int a) { cout << "Caught exception number: " << a << endl; return; } cout << "No exception detected!" << endl; return; }

Если выполнить этот фрагмент кода, то мы получим следующий результат:

Caught exception number: 1

Теперь закоментируйте строку throw 1; и функция выдаст такой результат:

No exception detected!

Как видите все очень просто, но если это применить с умом, такой подход покажется вам очень мощным средством обработки ошибок. Catch может "ловить" любой тип данных, так же как и throw может "кинуть" данные любого типа. Т.е. throw AnyClass(); будет правильно работать, так же как и catch (AnyClass &d) {};.

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

Catch(dumbclass) { }

так же, как и

Catch(dumbclass&) { }

Так же можно "поймать" и все исключения:

Catch(...) { }

Троеточие в этом случае показывает, что будут пойманы все исключения. При таком подходе нельзя указать имя переменной. В случае, если "кидаются" данные нестандартного типа (экземпляры определенных вами классов, структур и т.д.), лучше "ловить" их по ссылке, иначе вся "кидаемая" переменная будет скопирована в стек вместо того, чтобы просто передать указатель на нее. Если кидаются данные нескольких типов и вы хотите поймать конкретную переменную (вернее, переменную конкретного типа), то можно использовать несколько блоков catch, ловящих "свой" тип данных:

Try { throw 1; // throw "a"; } catch (long b) { cout << "пойман тип long: " << b << endl; } catch (char b) { cout << "пойман тип char: " << b << endl; }"

Создание" исключений

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

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

Перегрузка глобальных операторов new/delete

А сейчас хотелось бы отправить вас к статье "Как обнаружить утечку памяти". В ней рассказывается, как обнаружить неправильное управление распределением памяти в вашей программе. Вы можете спросить, при чем тут перегрузка операторов? Если перегрузить стандартные new и delete, то открываются широкие возможности по отслеживанию ошибок (причем ошибок часто критических) с помощью исключений. Например:

Char *a; try { a = new char; } catch (...){ // a не создан - обработать ошибку распределения памяти, // выйти из программы и т.п. } // a успешно создан, продолжаем выполнение

Это, на первый взгляд, кажется длиннее, чем стандартная проверка в С "а равен NULL?", однако если в программе выделяется десяток динамических переменных, то такой метод оправдывает себя.

Операторы throw без параметров

Итак, мы увидели, как новый метод обработки ошибок удобен и прост. Блок try-catch может содержать вложенные блоки try-catch и если не будет определено соответствующего оператора catch на текущем уровен вложения, исключение будет поймано на более высоком уровне. Единственная вещь, о которой вы должны помнить, - это то, что операторы, следующие за throw, никогда не выполнятся.

Try { throw; // ни один оператор, следующий далее (до закрывающей скобки) // выполнен не будет } catch(...) { cout << "Исключение!" << endl; }

Такой метод может применяться в случаях, когда не нужно передавать никаких данных в блок catch.

Приложение

Приведем пример, как все вышеизложенное может быть использовано в конкретном приложении. Преположим, у вас в программе есть класс cMain и экземпляр этого класса Main: class cMain { public: bool Setup(); bool Loop(); // Основной цикл программы void Close(); }; cMain Main;

А в функции main() или WinMain() вы можете использовать этот класс как-нибудь так:

Try { Main.Setup(); Main.Loop(); Main.Close(); } catch (Exception &e) { // использование класса, ведущего лог. log("Exception thrown: %s", e.String()); // Показываем сообщение об ошибке и закрываем приложение. }

Основной цикл программы может выглядеть примерно так:

While (AppActive) { try { // какие-то действия } catch (Exception &e) { /* Если исключение критическое, типа ошибки памяти, посылаем исключение дальше, в main(), оператором throw e; или просто throw. Если исключение некритично, обрабатываем его и возвращаемся в основной цикл. */ } }

Заключение

Метод обработки исключений, приведенный в статье, является удобным и мощным средством, однако только вам решать, использовать его или нет. Одно можно скачать точно - приведенный метод облегчит вам жизнь. Если хотите узнать об исключениях чуть больше, посмотрите публикацию