Иногда, во время работы программ, встречаются ситуации которые препятствуют дальнейшей нормальной их работе. К примеру при делении числа на ноль, программа завершит работу не смотря на то, сколько пользователь работал в программе, и какой объем данных внес. Программа просто закроется.
И представьте, если до этого пользователь вносил в программу данные несколько часов и проводил расчеты. При таком аварийном закрытии программы все эти данные и расчеты пропадут. Согласитесь – не очень приятно. Также может встретиться такая ситуация, когда программа пытается открыть недоступный в этот момент файл, или запросить больше, чем доступно памяти.
Такого рода ситуации программистам надо стараться предвидеть и строить программы так, чтобы они могли гибко реагировать, а не аварийно закрываться. В моей любимой книге Язык программирования C++. Лекции и упражнения автора С. Прата, дано следующее определение исключениям в С++:
Чтобы вам не сложно было понять механизм работы исключений в С++, рассмотрим их на простом примере. В нем мы предвидим тот случай, что в какой-то момент в ходе расчетов программы, может встретиться деление числа на 0. Наберите и скомпилируйте код, расположенный ниже. Чтобы убедиться в том, как реагирует программа на такую ситуацию, внесите число 0 в переменную num2 (она выступает делителем в примере).
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 29 30 | #include <iostream>; using namespace std; int main() { setlocale(LC_ALL, "rus"); int num1; int num2; int var = 3; // управляющая переменная для while while (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; var--; } cout << "Конец работы программы!" << endl << endl; return 0; } |
Так как переменная var равна 3, цикл while, в нормальной ситуации, должен отработать три раза. С каждым шагом цикла var уменьшается на единицу с помощью декремента. Но так как мы сразу внесли значение 0 в переменную num2, программа не пройдет до конца даже первый шаг цикла. Она прервется.
В следующем листинге, мы исправим это упущение – добавим несколько компонентов, которые помогут среагировать на данную ситуацию без прерывания работы программы. А именно:
- блок try или try-блок (попытка, проба);
- генератор исключения – блок throw (обработать, запустить);
- обработчик исключения, который его перехватывает -команда catch (поймать, ловить)
Как работает исключение? – Программист прописывает в коде (в try-блоке) конкретное условие, что если переменная num2 станет равна 0, то в таком случае необходимо генерировать исключение в throw. Далее, то что сгенерировал throw, перехватывает catch-блок (в виде параметра функции) и программа выполнит тот код, который прописан в этом блоке.
Пример:
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #include <iostream>; using namespace std; int main() { setlocale(LC_ALL, "rus"); int num1; int num2; int var = 3; while (var != 0) { cout << "Введите число num1: "; cin >> num1; cout << "Введите число num2: "; cin >> num2; cout << "num1 + num2 = " << num1 + num2 << endl; cout << "num1 / num2 = "; try // тут располагается код, который потенциально может вызвать ошибку { if (num2 == 0) { throw 999; // генерировать целое число 999 } cout << num1 / num2 << endl; } catch (int thr)// сюда передастся число, которое сгенерировал throw { cout << "Ошибка №" << thr << " - деление на 0!!!" << endl; } cout << "num1 - num2 = " << num1 - num2 << endl; cout << "=================================" << endl << endl; var--; } cout << "Программа завершила работу!" << endl << endl; return 0; } cout << "Программа завершила работу!" << endl << endl; return 0; } |
Разберем подробно. В строках 21-29 находится блок try. В нем необходимо размещать тот код, который может привести к необратимым ошибкам. Еще до арифметического выражения деления задаем условие: если num2 будет равно 0, то пусть throw генерирует число 999 (к примеру).
В том случае, сразу после генерации числа, дальнейшие команды в блоке try выполняться уже не будут, а само число “упадет” в блок catch (в виде параметра). Далее выполнится то, что указано в блоке catch – в нашем случае, это будет сообщение об ошибке:
cout << "Ошибка №" << thr << " - деление на 0!!!" << endl;
и программа будет выполнять последующие команды. В том случае, если число num2 != 0, то throw ничего не генерирует и catch-блок не сработает.
Посмотрите теперь, как отреагирует программа, если вы введете num2 равное нулю. Запускайте программу.
Как видим, там где могла произойти ошибка и досрочное завершение программы, мы увидели сообщение Ошибка №999 – деление на 0!!! Программа “перескочила” через операцию деления на 0 и выполнила catch-блок.
Чтобы вы лучше поняли, как значение генерируемое throw перехватывает catch-блок, замените код в строках 21 – 33 на этот:
1 2 3 4 5 6 7 8 9 10 11 12 | try { if (num2 == 0) { throw "Ошибка - деление на 0!!!!"; // генерируется строка cout << num1 / num2 << endl; } } catch (char *str) // строку перехватывает catch-блок { cout << str << endl; } |
В этом примере, если num2 равно 0, throw генерирует строку, а не число. Строка “падает” в catch-блок и выводится на экран.
Рассмотрим еще такой пример, когда исключение генерируется в функции, которая делит одно число на другое:
1 2 3 4 5 6 7 8 | int delenie(int n1, int n2) { if (n2 == 0) { throw 99; } return n1 / n2; }; |
Чтобы исключение сработало правильно, эту функцию надо вызвать в блоке try:
1 2 3 4 5 6 7 8 9 | try { cout << delenie(7, 0); cout << endl; } catch (int thr) { cout << "Ошибка №" << thr << " Деление на 0!!!" << endl; } |
catch перехватит число 99, а деление на 0 не состоится.
Основное, что нужно запомнить об исключениях в С++:
- В try-блоке (блоке повторных попыток) необходимо размещать код, который потенциально может привести к аварийному закрытию программы;
- Исключение генерируется в блоке throw. Если throw сработает программа автоматически приступит к выполнению команд catch-блока, игнорируя оставшийся код в try-блоке;
- Улавливающий блок – catch-блок, перехватывает то, что генерирует блок throw. Он обязательно должен находиться под try-блоком. Ничего не должно быть прописано между ними;
- catch-блок не сработает, если исключение не было сгенерировано. Программа его просто проигнорирует.
Вообще то, тема исключений в любом языке программирования – достаточно скользкая. Такой механизм вносит как свои преимущества, так и свои недостатки и скрытые опасности использования.
Язык C++ – производный от C, и в это развитие включили исключения. Следующее развитие (2008-2009г.г.) языка C – это язык Go. Из него исключения были разработчиками исключены и с очень обстоятельной опубликованной аргументацией почему они это сделали.
Реюме: исключения в C++ нужно использовать, но только там, где они крайне необходимы, где без них нельзя обойтись. В остальных случаях лучше использовать традиционный возврат кода ошибки.
Помогите люди добрые!!! Что неправильно с try у меня?
#include // содержит time()
#include
#include
using namespace std;
int main()
{
setlocale(LC_ALL, "rus");
int s1 = 0;
int s2 = 0;
char exit = 1;
int over = 0;
cout <<
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
cout << " Делите только у нас !!! \n";
cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
do
{
cout << "\n ~~~~~~~~~~ Введите ваши числа: ~~~~~~~~~~ \n";
cout < ";
cin >> s1;
cout < ";
cin >> s2;
try
{
over = s1 / s2;
cout < " << over << endl;
cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
cout << " Для продолжения вычислений нажми - 1, Для выхода - 0 \n";
cout << exit;
throw 999;
}
catch (int thr)
{
cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
cout << " ~~~~~~~~ Похоже ты допустил ошибку!!! ~~~~~~~~ ";
cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
}
} while (exit != 0);
return 0;
}
А у вас до throw дело не доходит – аварийное завершение наступает раньше, при делении на 0.
И параметром catch должно быть что-то, наследуемое от класса исключений:
catch( exception const& e ) {
Здравствуйте. У вас ошибка в третьем листинге.
cout << num1 / num2 << endl; //нужно вывести за пределы оператора if. иначе не работает.
Онлайн компилятор вообще не компилирует код с “try” и т.д. … – показывает ошибку
1). Нужно указывать КАКОЙ онлайн компилятор – их много, и есть совсем с придурью…
2). В разных стандартах C++ (например C++11) синтаксис записи блока try {} catch – может отличаться;
3). Многие онлайн компиляторы (лучшие) позволяют указать тот стандарт языка C++, который будет использоваться в коде;
I like more if-else, then try, because it don’t work from time to time.
Для тех у кого не работает код выше, используйте этот:
#include
using namespace std;
int main()
{
setlocale(LC_ALL, “rus”);
int num1;
int num2;
int var = 3;
while (var != 0)
{
cout <> num1;
cout <> num2;
cout << "num1 + num2 = " << num1 + num2 << endl;
cout << "num1 / num2 = ";
try // тут располагается код, который потенциально может вызвать ошибку
{
if (num2 == 0)
{
throw 999; // генерировать целое число 999
}
cout << num1 / num2 << endl;
}
catch (int thr)// сюда передастся число, которое сгенерировал throw
{
cout << "Ошибка №" << thr << " – деление на 0!!!" << endl;
}
cout << "num1 – num2 = " << num1 – num2 << endl;
cout << "=================================" << endl << endl;
var–;
}
cout << "Программа завершила работу!" << endl << endl;
return 0;
}
77el3m