En C++, les exceptions sont des anomalies d'exécution ou des conditions anormales qu'un programme rencontre lors de son exécution. Le processus de gestion de ces exceptions est appelé gestion des exceptions. Grâce au mécanisme de gestion des exceptions, le contrôle d'une partie du programme où l'exception s'est produite peut être transféré vers une autre partie du code.
Donc, essentiellement, en utilisant la gestion des exceptions en C++, nous pouvons gérer les exceptions afin que notre programme continue de s'exécuter.
trouver dans la carte C++
Qu’est-ce qu’une exception C++ ?
Une exception est un problème inattendu qui survient lors de l'exécution d'un programme. Notre programme se termine soudainement avec des erreurs/problèmes. Une exception se produit lors de l'exécution du programme (runtime).
Types d'exceptions C++
Il existe deux types d'exceptions en C++
- Synchrone: Exceptions qui se produisent lorsque quelque chose ne va pas en raison d'une erreur dans les données d'entrée ou lorsque le programme n'est pas équipé pour gérer le type de données actuel avec lequel il travaille, comme diviser un nombre par zéro.
- Asynchrone : Exceptions indépendantes de la volonté du programme, telles qu'une panne de disque, des interruptions du clavier, etc.
C++ essayer et attraper
C++ fournit une fonctionnalité intégrée pour la gestion des exceptions. Cela peut être fait en utilisant les mots-clés spécialisés suivants : essayer, attraper et lancer, chacun ayant un objectif différent.
Syntaxe de try-catch en C++
try { // Code that might throw an exception throw SomeExceptionType('Error message'); } catch ( ExceptionName e1 ) { // catch block catches the exception that is thrown from try block }> 1. essayez en C++
Le mot-clé try représente un bloc de code pouvant lever une exception placée à l'intérieur du bloc try. Il est suivi d’un ou plusieurs blocs catch. Si une exception se produit, le bloc try lève cette exception.
2. attraper en C++
L'instruction catch représente un bloc de code qui est exécuté lorsqu'une exception particulière est levée à partir du bloc try. Le code pour gérer l’exception est écrit dans le bloc catch.
3. ajouter du C++
Une exception en C++ peut être levée à l'aide du mot-clé throw. Lorsqu'un programme rencontre une instruction throw, il termine immédiatement la fonction en cours et commence à rechercher un bloc catch correspondant pour gérer l'exception levée.
Note: Plusieurs instructions catch peuvent être utilisées pour intercepter différents types d'exceptions levées par le bloc try.
Les mots-clés try et catch sont présentés par paires : nous utilisons le bloc try pour tester du code et si le code lève une exception, nous la gérerons dans notre bloc catch.
Pourquoi avons-nous besoin Gestion des exceptions en C++ ?
Voici les principaux avantages de la gestion des exceptions par rapport à la gestion traditionnelle des erreurs :
- Séparation du code de gestion des erreurs du code normal : Il existe toujours des conditions if-else pour gérer les erreurs dans les codes de gestion des erreurs traditionnels. Ces conditions et le code permettant de gérer les erreurs se confondent avec le flux normal. Cela rend le code moins lisible et maintenable. Avec les blocs try/catch, le code de gestion des erreurs devient séparé du flux normal.
- Les fonctions/méthodes ne peuvent gérer que les exceptions qu'elles choisissent : Une fonction peut lever de nombreuses exceptions, mais peut choisir d'en gérer certaines. Les autres exceptions, qui sont levées mais non interceptées, peuvent être gérées par l'appelant. Si l'appelant choisit de ne pas les intercepter, les exceptions sont gérées par l'appelant de l'appelant.
En C++, une fonction peut spécifier les exceptions qu'elle lève à l'aide du mot-clé throw. L'appelant de cette fonction doit gérer l'exception d'une manière ou d'une autre (soit en la spécifiant à nouveau, soit en l'interceptant).
- Regroupement des types d'erreurs : En C++, les types de base et les objets peuvent être générés comme exceptions. Nous pouvons créer une hiérarchie d'objets d'exception, regrouper les exceptions dans des espaces de noms ou des classes et les classer en fonction de leurs types.
Exemples de gestion des exceptions en C++
Les exemples suivants montrent comment utiliser un bloc try-catch pour gérer les exceptions en C++.
Exemple 1
L'exemple ci-dessous montre des exceptions levées en C++.
C++
// C++ program to demonstate the use of try,catch and throw> // in exception handling.> #include> #include> using> namespace> std;> int> main()> {> >// try block> >try> {> >int> numerator = 10;> >int> denominator = 0;> >int> res;> >// check if denominator is 0 then throw runtime> >// error.> >if> (denominator == 0) {> >throw> runtime_error(> >'Division by zero not allowed!'>);> >}> >// calculate result if no exception occurs> >res = numerator / denominator;> >//[printing result after division> >cout <<>'Result after division: '> << res << endl;> >}> >// catch block to catch the thrown exception> >catch> (>const> exception& e) {> >// print the exception> >cout <<>'Exception '> << e.what() << endl;> >}> >return> 0;> }> |
>
>Sortir
Exception Division by zero not allowed!>
Exemple 2
Ce qui suit est un exemple simple pour montrer la gestion des exceptions en C++. La sortie du programme explique le flux d'exécution des blocs try/catch.
RPC
// C++ program to demonstate the use of try,catch and throw> // in exception handling.> #include> using> namespace> std;> int> main()> {> >int> x = -1;> >// Some code> >cout <<>'Before try
'>;> >// try block> >try> {> >cout <<>'Inside try
'>;> >if> (x <0) {> >// throwing an exception> >throw> x;> >cout <<>'After throw (Never executed)
'>;> >}> >}> >// catch block> >catch> (>int> x) {> >cout <<>'Exception Caught
'>;> >}> >cout <<>'After catch (Will be executed)
'>;> >return> 0;> }> |
>
>Sortir
Before try Inside try Exception Caught After catch (Will be executed)>
Propriétés de la gestion des exceptions en C++
Propriété 1
Il existe un bloc catch spécial appelé bloc « catch-all », écrit catch(…), qui peut être utilisé pour intercepter tous les types d'exceptions.
Exemple
Dans le programme suivant, un int est lancé comme exception, mais il n'y a pas de bloc catch pour int, donc le bloc catch(…) sera exécuté.
RPC
// C++ program to demonstate the use of catch all> // in exception handling.> #include> using> namespace> std;> int> main()> {> >// try block> >try> {> >// throw> >throw> 10;> >}> >// catch block> >catch> (>char>* excp) {> >cout <<>'Caught '> << excp;> >}> >// catch all> >catch> (...) {> >cout <<>'Default Exception
'>;> >}> >return> 0;> }> |
>
>Sortir
Default Exception>
Propriété 2
La conversion de type implicite ne se produit pas pour les types primitifs.
Exemple
Dans le programme suivant, « a » n’est pas implicitement converti en int.
nœud de liste
RPC
//// C++ program to demonstate property 2: Implicit type> /// conversion doesn't happen for primitive types.> // in exception handling.> #include> using> namespace> std;> int> main()> {> >try> {> >throw> 'a'>;> >}> >catch> (>int> x) {> >cout <<>'Caught '> << x;> >}> >catch> (...) {> >cout <<>'Default Exception
'>;> >}> >return> 0;> }> |
Preity Zinta
>
>Sortir
Default Exception>
Sortir:
Default Exception>
Propriété 3
Si une exception est levée et n'est interceptée nulle part, le programme se termine anormalement.
Exemple
Dans le programme suivant, un caractère est lancé, mais il n'y a pas de bloc catch pour attraper le caractère.
RPC
// C++ program to demonstate property 3: If an exception is> // thrown and not caught anywhere, the program terminates> // abnormally in exception handling.> #include> using> namespace> std;> int> main()> {> >try> {> >throw> 'a'>;> >}> >catch> (>int> x) {> >cout <<>'Caught '>;> >}> >return> 0;> }> |
>
>
Sortir
terminate called after throwing an instance of 'char'>
Nous pouvons modifier ce comportement de terminaison anormal en écrivant notre fonction inattendue.
Note : Une exception de classe dérivée doit être interceptée avant une exception de classe de base.
Comme Java, la bibliothèque C++ possède un exception standard classe qui est la classe de base pour toutes les exceptions standard. Tous les objets lancés par les composants de la bibliothèque standard sont dérivés de cette classe. Par conséquent, toutes les exceptions standard peuvent être interceptées en interceptant ce type.
Propriété 4
Contrairement à Java, en C++, toutes les exceptions ne sont pas vérifiées, c'est-à-dire que le compilateur ne vérifie pas si une exception est interceptée ou non (voir ce pour plus de détails). Il n’est donc pas nécessaire de spécifier toutes les exceptions non interceptées dans une déclaration de fonction. Cependant, la gestion des exceptions est une pratique recommandée.
Exemple
Le programme suivant se compile correctement, mais idéalement, la signature de fun() devrait lister les exceptions non vérifiées.
RPC
Sridevi
// C++ program to demonstate property 4 in exception> // handling.> #include> using> namespace> std;> // This function signature is fine by the compiler, but not> // recommended. Ideally, the function should specify all> // uncaught exceptions and function signature should be> // 'void fun(int *ptr, int x) throw (int *, int)'> void> fun(>int>* ptr,>int> x)> {> >if> (ptr == NULL)> >throw> ptr;> >if> (x == 0)> >throw> x;> >/* Some functionality */> }> int> main()> {> >try> {> >fun(NULL, 0);> >}> >catch> (...) {> >cout <<>'Caught exception from fun()'>;> >}> >return> 0;> }> |
>
>Sortir
Caught exception from fun()>
Une meilleure façon d'écrire le code ci-dessus :
RPC
// C++ program to demonstate property 4 in better way> #include> using> namespace> std;> // Here we specify the exceptions that this function> // throws.> void> fun(>int>* ptr,>int> x)>throw>(> >int>*,>int>)>// Dynamic Exception specification> {> >if> (ptr == NULL)> >throw> ptr;> >if> (x == 0)> >throw> x;> >/* Some functionality */> }> int> main()> {> >try> {> >fun(NULL, 0);> >}> >catch> (...) {> >cout <<>'Caught exception from fun()'>;> >}> >return> 0;> }> |
>
>Sortir
Caught exception from fun()>
Note : L'utilisation de la spécification d'exception dynamique est obsolète depuis C++11. L'une des raisons peut être qu'il peut abandonner votre programme de manière aléatoire. Cela peut se produire lorsque vous lancez une exception d'un autre type qui n'est pas mentionné dans la spécification d'exception dynamique. Votre programme s'abandonnera car dans ce scénario, il appelle (indirectement) terminate(), qui appelle par défaut abort().
Propriété 5
En C++, les blocs try/catch peuvent être imbriqués. De plus, une exception peut être à nouveau levée en utilisant throw ; .
Exemple
Le programme suivant montre l’imbrication des blocs try/catch.
RPC
concaténation de chaînes java
// C++ program to demonstrate try/catch blocks can be nested> // in C++> #include> using> namespace> std;> int> main()> {> >// nesting of try/catch> >try> {> >try> {> >throw> 20;> >}> >catch> (>int> n) {> >cout <<>'Handle Partially '>;> >throw>;>// Re-throwing an exception> >}> >}> >catch> (>int> n) {> >cout <<>'Handle remaining '>;> >}> >return> 0;> }> |
>
>Sortir
Handle Partially Handle remaining>
Une fonction peut également relancer une fonction en utilisant le même lancer ; syntaxe. Une fonction peut gérer une partie et demander à l’appelant de gérer le reste.
Propriété 6
Lorsqu'une exception est levée, tous les objets créés à l'intérieur du bloc try englobant sont détruits avant que le contrôle ne soit transféré au bloc catch.
Exemple
Le programme suivant démontre la propriété ci-dessus.
RPC
// C++ program to demonstrate> #include> using> namespace> std;> // Define a class named Test> class> Test {> public>:> >// Constructor of Test> >Test() { cout <<>'Constructor of Test '> << endl; }> >// Destructor of Test> >~Test() { cout <<>'Destructor of Test '> << endl; }> };> int> main()> {> >try> {> >// Create an object of class Test> >Test t1;> >// Throw an integer exception with value 10> >throw> 10;> >}> >catch> (>int> i) {> >// Catch and handle the integer exception> >cout <<>'Caught '> << i << endl;> >}> }> |
>
>Sortir
Constructor of Test Destructor of Test Caught 10>
Limites de la gestion des exceptions en C++
La gestion des exceptions en C++ présente également quelques limitations :
- Les exceptions peuvent briser la structure ou le flux du code car plusieurs points de sortie invisibles sont créés dans le code, ce qui rend le code difficile à lire et à déboguer.
- Si la gestion des exceptions n’est pas effectuée correctement, cela peut également entraîner des fuites de ressources.
- Il est difficile d’apprendre à écrire du code d’exception sûr.
- Il n'existe pas de norme C++ sur la façon d'utiliser la gestion des exceptions, il existe donc de nombreuses variations dans les pratiques de gestion des exceptions.
Conclusion
La gestion des exceptions en C++ est utilisée pour gérer les événements inattendus à l'aide de blocs try and catch pour gérer efficacement le problème. Cette gestion des exceptions rend nos programmes plus fiables car les erreurs au moment de l'exécution peuvent être traitées séparément et elle aide également à empêcher le programme de planter et de s'arrêter brusquement en cas d'erreur.
Articles Liés:
- Principales questions et réponses d'entretien sur la gestion des exceptions C++
- Quiz sur la gestion des exceptions en C++