Tratamento de exceções C ++

Uma exceção é um problema que surge durante a execução de um programa. Uma exceção C ++ é uma resposta a uma circunstância excepcional que surge durante a execução de um programa, como uma tentativa de divisão por zero.

As exceções fornecem uma maneira de transferir o controle de uma parte de um programa para outra. O tratamento de exceções C ++ é baseado em três palavras-chave:try, catch, e throw.

  • throw- Um programa lança uma exceção quando um problema aparece. Isso é feito usando umthrow palavra-chave.

  • catch- Um programa captura uma exceção com um tratador de exceção no local de um programa onde você deseja tratar o problema. ocatch palavra-chave indica a captura de uma exceção.

  • try - A trybloco identifica um bloco de código para o qual determinadas exceções serão ativadas. É seguido por um ou mais blocos de captura.

Assumindo que um bloco levantará uma exceção, um método captura uma exceção usando uma combinação de try e catchpalavras-chave. Um bloco try / catch é colocado ao redor do código que pode gerar uma exceção. O código dentro de um bloco try / catch é referido como código protegido, e a sintaxe para usar try / catch da seguinte forma -

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

Você pode listar vários catch declarações para capturar diferentes tipos de exceções no caso de seu try block levanta mais de uma exceção em diferentes situações.

Lançamento de exceções

As exceções podem ser lançadas em qualquer lugar dentro de um bloco de código usando throwdeclaração. O operando da instrução throw determina um tipo para a exceção e pode ser qualquer expressão e o tipo do resultado da expressão determina o tipo de exceção lançada.

A seguir está um exemplo de lançamento de uma exceção quando ocorre a divisão por zero -

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

Captura de exceções

o catch bloco seguindo o trybloco captura qualquer exceção. Você pode especificar o tipo de exceção que deseja capturar e isso é determinado pela declaração de exceção que aparece entre parênteses após a palavra-chave catch.

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

O código acima irá capturar uma exceção de ExceptionNametipo. Se você quiser especificar que um bloco catch deve lidar com qualquer tipo de exceção que é lançada em um bloco try, você deve colocar reticências, ..., entre os parênteses envolvendo a declaração de exceção da seguinte maneira -

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

A seguir está um exemplo, que lança uma exceção de divisão por zero e capturamos no bloco 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;
}

Porque estamos levantando uma exceção do tipo const char*, portanto, ao capturar essa exceção, temos que usar const char * no bloco catch. Se compilarmos e executarmos o código acima, isso produzirá o seguinte resultado -

Division by zero condition!

Exceções padrão C ++

C ++ fornece uma lista de exceções padrão definidas em <exception> que podemos usar em nossos programas. Eles são organizados em uma hierarquia de classes pai-filho mostrada abaixo -

Aqui está uma pequena descrição de cada exceção mencionada na hierarquia acima -

Sr. Não Exceção e descrição
1

std::exception

Uma exceção e classe pai de todas as exceções padrão do C ++.

2

std::bad_alloc

Isso pode ser jogado por new.

3

std::bad_cast

Isso pode ser jogado por dynamic_cast.

4

std::bad_exception

Este é um dispositivo útil para lidar com exceções inesperadas em um programa C ++.

5

std::bad_typeid

Isso pode ser jogado por typeid.

6

std::logic_error

Uma exceção que teoricamente pode ser detectada lendo o código.

7

std::domain_error

Esta é uma exceção lançada quando um domínio matematicamente inválido é usado.

8

std::invalid_argument

Isso é lançado devido a argumentos inválidos.

9

std::length_error

Isso é lançado quando um std :: string muito grande é criado.

10

std::out_of_range

Isso pode ser lançado pelo método 'at', por exemplo um std :: vector e std :: bitset <> :: operator [] ().

11

std::runtime_error

Uma exceção que teoricamente não pode ser detectada pela leitura do código.

12

std::overflow_error

Isso é lançado se ocorrer um estouro matemático.

13

std::range_error

Isso ocorre quando você tenta armazenar um valor que está fora do intervalo.

14

std::underflow_error

Isso é lançado se ocorrer um estouro negativo matemático.

Definir novas exceções

Você pode definir suas próprias exceções herdando e substituindo exceptionfuncionalidade da classe. A seguir está o exemplo, que mostra como você pode usar a classe std :: exception para implementar sua própria exceção de maneira padrão -

#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
   }
}

Isso produziria o seguinte resultado -

MyException caught
C++ Exception

Aqui, what()é um método público fornecido pela classe de exceção e foi substituído por todas as classes de exceção filho. Isso retorna a causa de uma exceção.