Gestion des exceptions C++


Les exceptions sont des problèmes qui surviennent lors de l'exécution du programme. Les exceptions C++ sont des situations particulières qui se produisent lors de l'exécution d'un programme, comme une tentative de division par zéro.

Les exceptions permettent de transférer le contrôle d'un programme. La gestion des exceptions C++ implique trois mots-clés : try, catch et throw.

  • throw : Lorsqu'un problème survient, le programme lèvera une exception. Cela se fait à l'aide du mot-clé throw.

  • catch : Attrapez l'exception via un gestionnaire d'exceptions au point où vous souhaitez gérer le problème. Le mot clé catch est utilisé pour intercepter les exceptions.

  • try : Le code dans le bloc try identifie l'exception spécifique qui sera déclenchée. Il est généralement suivi d'un ou plusieurs blocs catch.

Si un bloc lève une exception, la méthode pour intercepter l'exception utilisera les mots-clés try et catch. Le code susceptible de générer des exceptions est placé dans le bloc try. Le code du bloc try est appelé code de protection. La syntaxe d'utilisation des instructions try/catch est la suivante :

try
{
   // 保护代码
}catch( ExceptionName e1 )
{
   // catch 块
}catch( ExceptionName e2 )
{
   // catch 块
}catch( ExceptionName eN )
{
   // catch 块
}

Si le bloc try lèvera différentes exceptions dans différentes situations, vous pouvez essayer de lister plusieurs catch instruction, utilisée pour intercepter différents types d’exceptions.

Throw Exception

Vous pouvez lever une exception n'importe où dans un bloc de code à l'aide de l'instruction throw. L'opérande de l'instruction throw peut être n'importe quelle expression et le type du résultat de l'expression détermine le type d'exception levée.

Ce qui suit est un exemple d'exception levée lors d'une tentative de division par zéro :

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

catch exception

catch bloc suivi de try bloc, utilisé pour intercepter les exceptions. Vous pouvez spécifier le type d'exception que vous souhaitez intercepter, qui est déterminé par la déclaration d'exception entre parenthèses après le mot-clé catch.

try
{
   // 保护代码
}catch( ExceptionName e )
{
  // 处理 ExceptionName 异常的代码
}

Le code ci-dessus interceptera une exception de type ExceptionName. Si vous souhaitez que le bloc catch soit capable de gérer tout type d'exception levée par le bloc try, vous devez utiliser des points de suspension... entre parenthèses dans la déclaration d'exception, comme ceci :

try
{
   // 保护代码
}catch(...)
{
  // 能处理任何异常的代码
}

Voici un exemple , lancez une exception de division par zéro et interceptez l'exception dans un bloc 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;
}

Puisque nous lançons une exception de type const char*, lors de l'interception de l'exception, nous devons utiliser const char* dans le bloc catch. Lorsque le code ci-dessus est compilé et exécuté, il produira les résultats suivants :

Division by zero condition!

Exceptions standard C++

C++ fournit une série d'exceptions standard, définies dans <exception> ;, nous pouvons utiliser ces exceptions standards dans nos programmes. Ils sont organisés dans une hiérarchie de classes parent-enfant comme suit :

cpp_exceptions.jpg

Le tableau suivant est une description de chaque exception qui se produit dans la hiérarchie ci-dessus :

异常描述
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该异常可以通过方法抛出,例如 std::vector 和 std::bitset<>::operator[]()。
std::runtime_error理论上不可以通过读取代码来检测到的异常。
std::overflow_error当发生数学上溢时,会抛出该异常。
std::range_error当尝试存储超出范围的值时,会抛出该异常。
std::underflow_error当发生数学下溢时,会抛出该异常。

Définir de nouvelles exceptions

Vous pouvez définir de nouvelles exceptions en héritant et en surchargeant la classe exception. L'exemple suivant montre comment utiliser la classe std::exception pour implémenter vos propres exceptions :

#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)
  {
    //其他的错误
  }
}

Cela produira les résultats suivants :

MyException caught
C++ Exception

Ici, what() Est une méthode publique fournie par la classe d'exception, qui a été surchargée par toutes les sous-classes d'exception. Cela renverra la raison de l’exception.