C ++

Обработка исключений в C ++

Обработка исключений в C ++
Существует три типа программных ошибок. Это синтаксические ошибки, логические ошибки и ошибки времени выполнения.

Ошибки синтаксиса

Неправильно набранное выражение, инструкция или конструкция - синтаксическая ошибка.

Рассмотрим следующие два утверждения:

int arr [] = 1, 2, 3; //верный
int arr = 1, 2, 3; // синтаксическая ошибка, отсутствует []

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

Логическая ошибка

Логическая ошибка - это ошибка, совершаемая программистом при неправильном логическом кодировании. Это может быть результатом незнания программистом функций языка программирования или непонимания того, что программа должна делать.

В этой ситуации программа компилируется успешно. Программа работает нормально, но дает неверные результаты. Такая ошибка может быть из-за того, что цикл повторяется 5 раз, а цикл повторяется 10 раз. Также может случиться так, что цикл бессознательно заставлен повторяться бесконечно. Единственный способ решить эту проблему - это тщательно программировать и тщательно тестировать программу, прежде чем передать ее заказчику.

Ошибки во время выполнения

Неправильные или исключительные вводы вызывают ошибки времени выполнения. В этом случае программа была успешно скомпилирована и хорошо работает во многих ситуациях. В определенных ситуациях программа вылетает (и останавливается).

Представьте, что в сегменте программного кода число 8 нужно разделить на несколько знаменателей. Таким образом, если числитель 8 разделить на знаменатель 4, ответ (частное) будет 2. Однако, если пользователь вводит 0 в качестве знаменателя, программа выйдет из строя. Деление на 0 запрещено в математике, а также в вычислениях. При программировании следует избегать деления на ноль. Обработка исключений обрабатывает ошибки времени выполнения, например деление на ноль. В следующей программе показано, как решить проблему деления на ноль без использования функции исключения в C ++:

#включать
используя пространство имен std;
int main ()

int числитель = 8;
int знаменатель = 2;
если (знаменатель != 0)

int результат = числитель / знаменатель;
cout << result << '\n';

еще

cout << "Division by zero is not permitted!" << '\n';

возврат 0;

Выход 4. Если бы знаменатель был равен 0, результат был бы следующим:

«Деление на ноль недопустимо!”

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

Функция исключения в C ++ использует блок try для блока if и блок catch для блока else для обработки ошибки, как показано ниже:

#включать
используя пространство имен std;
int main ()

int числитель = 8;
int знаменатель = 2;
пытаться

если (знаменатель != 0)

int результат = числитель / знаменатель;
cout << result << '\n';

еще

бросить 0;


поймать (int err)

если (ошибка == 0)
cout << "Division by zero is not permitted!" << '\n';

возврат 0;

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

В этой статье объясняется обработка исключений в C++. Базовые знания C ++ являются обязательным условием для понимания читателем этой статьи.

Содержание статьи:

  • Функция, выбрасывающая исключение
  • Более одного блока захвата для одного блока попытки
  • Вложенные блоки try / catch
  • noexcept-спецификатор
  • Специальная функция std :: terminate ()
  • Заключение

Функция, выбрасывающая исключение:

Функция также может генерировать исключение, как и блок try. Бросок происходит в пределах определения функции. Следующая программа иллюстрирует это:

#включать
используя пространство имен std;
пустота fn (const char * str)

if (islower (str [0]))
бросить 'l';

int main ()

пытаться

fn ("кузнец");

поймать (char ch)

если (ch == 'l')
cout << "Person's name cannot begin in lowercase!" << '\n';

возврат 0;

Обратите внимание, что на этот раз в блоке try есть только вызов функции. Это вызываемая функция, которая имеет операцию throw. Блок catch перехватывает исключение, и на выходе получается:

«Имя человека не может начинаться с нижнего регистра!”

На этот раз брошенный и пойманный тип - это символ.

Более одного блока отлова на один блок попытки:

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

#включать
используя пространство имен std;
char input = '*';
int main ()

пытаться

если (isdigit (ввод))
бросить 10;
если (isalpha (вход))
бросить 'z';

поймать (число)

cout << "Digit input is forbidden!" << '\n';

поймать (символ)

cout << "Character input is forbidden!" << '\n';

возврат 0;

Нет выхода. Если бы значение ввода было цифрой, e.грамм., '1', результат был бы таким:

"Ввод цифр запрещен!"

Если бы значение ввода было алфавитом, e.грамм., 'a', результат был бы таким:

"Ввод символов запрещен!"

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

Для улова важен тип; улов должен соответствовать типу брошенного операнда. Конкретное значение выданного аргумента (операнда) может быть использовано для дальнейшей проверки, если это необходимо.

Более одного обработчика для одного и того же типа

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

#включать
используя пространство имен std;
char input = '1';
int main ()

пытаться

если (isdigit (ввод))
бросить 10;

поймать (число)

cout << "Digit input is forbidden!" << '\n';

поймать (число)

cout << "Not allowed at all: digit input!" << '\n';

возврат 0;

Результат:

"Ввод цифр запрещен!"

Вложенные блоки try / catch:

блоки try / catch могут быть вложенными. Вышеупомянутая программа для ввода с клавиатуры не буквенно-цифровых символов повторяется здесь, но с вложенным буквенным кодом ошибки:

#включать
используя пространство имен std;
char input = '*';
int main ()

пытаться

если (isdigit (ввод))
бросить 10;
пытаться

если (isalpha (вход))
бросить 'z';

поймать (символ)

cout << "Character input is forbidden!" << '\n';


поймать (число)

cout << "Digit input is forbidden!" << '\n';

возврат 0;

Буквенный блок ошибки try / catch вложен в блок try цифрового кода. Работа этой программы и предыдущая операция, из которой она скопирована, идентичны.

noexcept-спецификатор

Рассмотрим следующую функцию:

void fn (const char * str) noexcept

if (islower (str [0]))
бросить 'l';

Обратите внимание на спецификатор noexcept сразу после правой круглой скобки в списке параметров функции. Это означает, что функция не должна генерировать исключение. Если функция выдает исключение, как в этом случае, она скомпилируется с предупреждающим сообщением, но не запустится. Попытка запустить программу вызовет специальную функцию std :: terminate (), которая должна корректно остановить программу, а не просто позволить ей буквально вылететь.

Спецификатор noexcept находится в разных формах. Это следующие:

введите func () noexcept; : не допускает выражения throw
введите func () noexcept (true); : позволяет бросить выражение
введите func () throw (); : не допускает выражения throw
введите func () noexcept (false); : позволяет использовать выражение throw, которое является необязательным
введите func (); : позволяет использовать выражение throw, которое является необязательным

true или false в круглых скобках можно заменить выражением, результатом которого будет true или false.

Специальная функция std :: terminate ():

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

Напечатайте, скомпилируйте и запустите следующую программу:

#включать
используя пространство имен std;
char input = '1';
int main ()

пытаться

если (isdigit (ввод))
бросить 10;

поймать (число)

бросать;

возврат 0;

После успешной компиляции программа завершилась без запуска, и сообщение об ошибке с компьютера автора:

«Terminate вызывается после выброса экземпляра 'int'

Прервано (ядро выгружено) »

Заключение:

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

Битва за Веснот 1.13.6 Выпущена разработка
Битва за Веснот 1.13.6, выпущенная в прошлом месяце, является шестой разработкой в ​​1.13.x и содержит ряд улучшений, в первую очередь пользовательско...
Как установить League Of Legends на Ubuntu 14.04
Если вы поклонник League of Legends, то это возможность для вас протестировать League of Legends. Обратите внимание, что LOL поддерживается в PlayOnLi...
Установите последнюю версию игры OpenRA Strategy в Ubuntu Linux
OpenRA - это игровой движок Libre / Free Real Time Strategy, воссоздающий ранние игры Westwood, такие как классическая Command & Conquer: Red Alert. Р...