Unetway

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

Исключением является проблема, возникающая во время выполнения программы. Исключение C ++ - это ответ на исключительное обстоятельство, которое возникает во время работы программы, например попытка деления на ноль.

Исключения обеспечивают способ передачи контроля из одной части программы в другую. Обработка исключений C ++ построена на трех ключевых словах: try, catch и throw .

  • throw - программа выдает исключение, когда возникает проблема. Это делается с использованием ключевого слова throw .
  • catch - программа выхватывает исключение с обработчиком исключений в месте в программе, где вы хотите справиться с этой проблемой. Ключевое слово catch указывает на отлов исключения.
  • try - блок try идентифицирует блок кода, для которого будут активированы определенные исключения. За ним следует один или несколько блоков catch.

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

try {
   // protected code
} catch( ExceptionName e1 ) {
   // catch block
} catch( ExceptionName e2 ) {
   // catch block
} catch( ExceptionName eN ) {
   // catch block
}

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

Выбросы исключений

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

Ниже приведен пример исключения исключения при делении на нулевое условие:

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

Устранение исключений

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

try {
   // protected code
} catch( ExceptionName e ) {
  // code to handle ExceptionName exception
}

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

try {
   // protected code
} catch(...) {
  // code to handle any exception
}

Ниже приведен пример, который генерирует деление на ноль, и мы поймаем его в блоке catch.

#include <iostream>
using namespace std;

double division(int a, int b) {
   if( b == 0 ) {
      throw "Division by zero condition!";
   }
   return (a/b);
}

int main () {
   int x = 50;
   int y = 0;
   double z = 0;
 
   try {
      z = division(x, y);
      cout << z << endl;
   } catch (const char* msg) {
     cerr << msg << endl;
   }

   return 0;
}

Поскольку мы создаем исключение типа const char * , поэтому, поймав это исключение, мы должны использовать const char * в блоке catch. Если мы скомпилируем и запустим код выше, это приведет к следующему результату:

Division by zero condition!

Стандартные исключения C ++

C ++ предоставляет список стандартных исключений, определенных в <exception>, которые мы можем использовать в наших программах.  Вот небольшое описание каждого исключения, упомянутого в приведенной выше иерархии:

std::exception Исключение и родительский класс всех стандартных исключений C ++.
std::bad_alloc Это может быть брошено new
std::bad_cast Это может быть вызвано dynamic_cast .
std::bad_exception Это полезное устройство для обработки неожиданных исключений в программе на C ++.
std::bad_typeid Это может быть вызвано typeid .
std::logic_error Исключение, которое теоретически можно обнаружить, прочитав код.
std::domain_error Это исключение, возникшее при использовании математически недопустимого домена.
std::invalid_argument Это вызвано неправильными аргументами.
std::length_error Это генерируется при создании слишком большой std :: string.
std::out_of_range Это может быть вызвано методом «at», например, std :: vector и std :: bitset <> :: operator [] ().
std::runtime_error Исключение, которое теоретически невозможно обнаружить, прочитав код.
std::overflow_error Это бросается, если происходит математическое переполнение.
std::range_error Это происходит, когда вы пытаетесь сохранить значение, выходящее за пределы допустимого диапазона.
std::underflow_error Это бросается, если происходит математическое недополнение.

Определение новых исключений

Вы можете определить свои собственные исключения, наследуя и переопределяя функциональные возможности класса исключений . Ниже приведен пример, который показывает, как вы можете использовать класс std :: exception для реализации своего собственного исключения стандартным способом -

#include <iostream>
#include <exception>
using namespace std;

struct MyException : public exception {
   const char * what () const throw () {
      return "C++ Exception";
   }
};
 
int main() {
   try {
      throw MyException();
   } catch(MyException& e) {
      std::cout << "MyException caught" << std::endl;
      std::cout << e.what() << std::endl;
   } catch(std::exception& e) {
      //Other errors
   }
}

Это приведет к следующему результату -

MyException caught
C++ Exception

Здесь what() - это открытый метод, предоставляемый классом исключений, и он был переопределен всеми дочерними классами исключений. Это возвращает причину исключения.