Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Infa (1)

.pdf
Скачиваний:
6
Добавлен:
14.04.2015
Размер:
2 Мб
Скачать
☆

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

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

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

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

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

char *a; try

{

a = new char[10];

}

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.

Если исключение некритично, обрабатываем его и возвращаемся в основной цикл. */

}

}

Заключение

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

Всем нам интуитивно, чтопонятнотакое исключение. Это некое действие, кот силу, при наступлении нестандартнойГоворяситуациио об .сключениях в С++, ра

одну из таких нестандартных—делениеситуацийна 0. Представьте, что мы р программе, где ювручнувносим много числовых данныхрезультате.Далее, -вкакихто расчетов программы, значение одной из переменных0. А встанетследующейравнымстро кода это значение выступает делителем. Конечно,приведетэток днействиеизбежном закрытию программыодуи выхиз нееИвы. можете себе представить свое состо полчаса вводите данные, работая в этой программе,-то этапеи она какомпрост перестает работать и закрывается, а все данные пропадают.

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

Сначала наберите исходный код ниже и скомпилируйтеnum2 внесите.В переменнуючисло0, чтобы у вас было понимание той проблемы, что если в программе вс она резко прекращаетту, рабохотите вы этого или нет.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

#include <iostream>; usingnamespacestd;

intmain()

{

setlocale(LC_ALL, "rus");

intnum1;

intnum2;

intvar = 2; //управляющая переменная для while

while(var--) //пока var - истина (не равно 0)

{

cout << "Введите значение num1: "; cin >> num1;

cout << "Введите значение num2: "; cin >> num2;

cout << "num1 + num2 = "<< num1 + num2 << endl; cout << "num1 / num2 = "<< num1 / num2 << endl; cout << "num1 - num2 = "<< num1 - num2 << endl;

cout << "================================="<< endl << endl;

}

cout << "Программа завершила работу!"<< endl << endl;

return0;

}

В программе цикл должен отработатьстрокедва12 мыразапередаем.В циклу значен переменнойvar и в этой же строке уменьшаем её на единицу операциюдекремента(var--). Но,если в переменнуюnum2 будет введено значение0, мы увидим только результатa сложения+ b программа завершит работу не зависи есть код ниже или нет, отработал цикл или нет.

Используя исключения, мы сможем избежатьЧтобытаких«пкрутить»проблем.исключение к этому примеру, надо познакомиться со следующимиthrow (вкомандамипереводе—С++: обработать,запустить),try (попытка),catch (поймать, ловить).В исходном код исключение сработает так:получаетпрограммаконкретное отуказаниепрограммиста—если значение определённой переменной в определённомtry-блоке)участке будеткода равно0, то в этом случае пусть генерируетсяthrow. исключениеЭтоисключение автоматически передастсяcatch-блоку в виде параметра и выполнитсягоблокакод. это

Сразу рассмотрим пример. А все подробные пояснения по исходному располагатьсяпод ним:

1

2

3#include <iostream>;

4usingnamespacestd;

5

6intmain()

7{

8

setlocale(LC_ALL, "rus");

 

9

intnum1;

10

intnum2;

11

intvar = 2;

12

 

13

while(var--)

14

{

15

cout << "Введите значение num1: ";

cin >> num1;

16

cout << "Введите значение num2: ";

 

17

cin >> num2;

18

 

19

cout << "num1 + num2 = "<< num1 + num2 << endl;

20

cout << "num1 / num2 = ";

 

21

try//код, который может привести к ошибке, располагается тут

22

{

23

if(num2 == 0)

24

{

25

throw123; //генерировать целое число 123

26

}

cout << num1 / num2 << endl;

27

}

 

28

catch(inti)//сюдапередастсячисло 123

29

{

30

cout << "Ошибка №"<< i << " - на 0 делить нельзя!!!!"<< endl;

}

31

 

32

cout << "num1 - num2 = "<< num1 - num2 << endl;

 

33cout << "================================="<< endl << endl;

34}

35

36 cout << "Программа завершила работу!"<< endl << endl;;

37

38return0;

39}

40

41

42

В строках 22 — 29 определенtry-блок. В располагаетсянем код, который потен может вызвать ошибку в работе программы, а именно ошибку0. Задаемв случа условиеif — еслиnum2 равно0, то генерироватьцелое число123,к примеру. В это случаеtry-блок сразу прекращает выполльнейшихние дакоманд, а123число«падает» вcatch. В нашем примере он выводит сообщение об ошибке. При этом п работать выполнятьи команды, размещенные ниже. num2Еслине жебудетчислоравно нулю, втоtry-блокевыполнитсякомандаcout << num1 / num2 << endl; ,аcatch не сработает.

Запускаем программу и в первом шаге цикла вводимnum2значеравноие0, перема во втором—любое другое число:

CppStudio.com

Введите

 

 

 

значение

 

 

 

num1:

 

50

Введите

 

 

 

значение

 

 

 

num2:

 

0

num1

 

 

+

 

num2

 

 

 

=

50

num1

/

num2

=

Ошибка

№123

—

на

0

делить

нельзя!!!!

num1

 

 

—

 

num2

 

 

 

=

50

=================================

 

 

 

 

 

 

Введите

 

 

 

значение

 

 

 

num1:

 

50

Введите

 

 

 

значение

 

 

 

num2:

 

5

num1

 

 

+

 

num2

 

 

 

=

55

num1

 

 

/

 

num2

 

 

 

=

10

num1

 

 

—

 

num2

 

 

 

=

45

=================================

Программа завершила работу!

Как видно, деление0 произошлона и программа не прекратила свою работ мы увидели сообщение об ошибке в строке, где должна была произо на0.

Чтобы лучше понять, как именно значение, throwкотороепер дагетсянерируетcatchв, попробуйте заменить участокстрок 22 —кода33 на следующий код:

1

2

try

3

{

if(num2 == 0)

4

{

5

throw"Ошибка - на 0 делить нельзя!!!!"; //генерировать символьную строк

6

}

7cout << num1 / num2 << endl;

8}

catch(char*str)//сюда передастся строка

9{

10cout << str << endl;

11}

12

Тут при попытке

деления0, throw

генерируетна не число, а символьнуюИ

 

 

блоку

catch

в скобкахпоказываем,мы

что он будет принимать указатель— на

выводить строкуэту на

экран.

 

1

intdivision(intn1, intn2)

2

{

3

if(n2 == 0)

4

{

5

throw99;

Исключение так же может генерироваться в определенной прогр Например, у нас определена функция деления двух целых чисел и в ней деление на 0.

6 }

7

returnn1 / n2;

}

8

 

А вызывать эту функцию, конечноtry-блокенадо. в

1

2try

{

3cout << division(5, 0);

4cout << endl;

5}

6catch(inti)

7

{

cout<< "Ошибка №"<<i<< " Делениенаноль."<< endl;

8

}

 

9

 

Деление нольна не состоитсяcatch поймаети число99.

Что важно запомнить об исключениях:

try-блок— так называемый блок повторных попыток. В немкод,надо который может привести к ошибке и аварийному закрытию програ

throw генерирует исключениечто. остановитТо tryра-ботулока и приведет выполнению кодаcatch-блока. Тип исключения должен соответство принимаемого аргументаcatch-блока;

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

если tryв -блоке исключение не генерировалось,catch-блок сработает. Програ его обойдет.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]