En C++, les excepcions són anomalies en temps d'execució o condicions anormals que es troba un programa durant la seva execució. El procés de gestió d'aquestes excepcions s'anomena maneig d'excepcions. Mitjançant el mecanisme de gestió d'excepcions, el control d'una part del programa on s'ha produït l'excepció es pot transferir a una altra part del codi.
Així, bàsicament, utilitzant el maneig d'excepcions en C++, podem gestionar les excepcions perquè el nostre programa continuï funcionant.
btree i b tree
Què és una excepció de C++?
Una excepció és un problema inesperat que sorgeix durant l'execució d'un programa, el nostre programa acaba de sobte amb alguns errors/problemes. L'excepció es produeix durant l'execució del programa (temps d'execució).
Tipus d'excepció C++
Hi ha dos tipus d'excepcions en C++
- Sincrònic: Excepcions que es produeixen quan alguna cosa va malament a causa d'un error en les dades d'entrada o quan el programa no està equipat per gestionar el tipus de dades actual amb què treballa, com ara dividir un nombre per zero.
- Asíncron : Excepcions que estan fora del control del programa, com ara fallades del disc, interrupcions del teclat, etc.
C++ intenta i atrapa
C++ proporciona una característica integrada per a la gestió d'excepcions. Es pot fer utilitzant les següents paraules clau especialitzades: provar, agafar i llançar amb cadascuna d'elles amb un propòsit diferent.
Sintaxi 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. prova en C++
La paraula clau try representa un bloc de codi que pot generar una excepció col·locada dins del bloc try. Va seguit d'un o més blocs de captura. Si es produeix una excepció, proveu de bloqueig que llanci aquesta excepció.
2. captura en C++
La sentència catch representa un bloc de codi que s'executa quan es llança una excepció determinada des del bloc try. El codi per gestionar l'excepció està escrit dins del bloc catch.
3. introduir C++
Una excepció en C++ es pot llançar mitjançant la paraula clau throw. Quan un programa troba una instrucció de llançament, immediatament finalitza la funció actual i comença a trobar un bloc catch coincident per gestionar l'excepció llançada.
Nota: Es poden utilitzar diverses declaracions catch per detectar diferents tipus d'excepcions llançades pel bloc try.
Les paraules clau try and catch vénen per parelles: fem servir el bloc try per provar algun codi i si el codi genera una excepció, la gestionarem al nostre bloc catch.
Per què necessitem Gestió d'excepcions en C++?
Els següents són els principals avantatges de la gestió d'excepcions respecte a la gestió d'errors tradicional:
- Separació del codi de gestió d'errors del codi normal : Sempre hi ha condicions si no per gestionar els errors en els codis de gestió d'errors tradicionals. Aquestes condicions i el codi per gestionar els errors es barregen amb el flux normal. Això fa que el codi sigui menys llegible i fàcil de mantenir. Amb els blocs try/catch, el codi per a la gestió d'errors esdevé separat del flux normal.
- Les funcions/Mètodes només poden gestionar les excepcions que trien : Una funció pot generar moltes excepcions, però pot optar per gestionar-ne algunes. Les altres excepcions, que es llancen però no s'atrapen, les pot gestionar la persona que truca. Si la persona que truca decideix no captar-les, llavors les excepcions les gestiona la persona que truca.
En C++, una funció pot especificar les excepcions que llança mitjançant la paraula clau throw. La persona que truca d'aquesta funció ha de gestionar l'excepció d'alguna manera (ja sigui especificant-la de nou o capturant-la).
- Agrupació de tipus d'error : En C++, tant els tipus bàsics com els objectes es poden llançar com a excepcions. Podem crear una jerarquia d'objectes d'excepció, agrupar excepcions en espais de noms o classes i classificar-les segons els seus tipus.
Exemples de gestió d'excepcions en C++
Els exemples següents mostren com utilitzar un bloc try-catch per gestionar les excepcions en C++.
Exemple 1
L'exemple següent mostra les excepcions de llançament 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;> }> |
>
>Sortida
Exception Division by zero not allowed!>
Exemple 2
El següent és un exemple senzill per mostrar el maneig d'excepcions en C++. La sortida del programa explica el flux d'execució dels blocs try/catch.
CPP
// 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;> }> |
pandes loc
>
>Sortida
Before try Inside try Exception Caught After catch (Will be executed)>
Propietats del maneig d'excepcions en C++
Propietat 1
Hi ha un bloc catch especial anomenat bloc 'catch-all', escrit com catch (...), que es pot utilitzar per capturar tot tipus d'excepcions.
Exemple
Al programa següent, es llança un int com a excepció, però no hi ha cap bloc catch per a int, de manera que s'executarà el bloc catch(…).
CPP
// 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;> }> |
>
>Sortida
Default Exception>
Propietat 2
La conversió implícita de tipus no es produeix amb els tipus primitius.
Exemple
Al programa següent, 'a' no es converteix implícitament a int.
CPP
//// 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;> }> |
>
>Sortida
Default Exception>
Sortida:
Default Exception>
Propietat 3
Si es llança una excepció i no es detecta enlloc, el programa finalitza de manera anormal.
matriu js
Exemple
Al programa següent, es llança un caràcter, però no hi ha cap bloc catch per atrapar el caràcter.
CPP
// 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;> }> |
>
>
Sortida
terminate called after throwing an instance of 'char'>
Podem canviar aquest comportament de terminació anormal escrivint la nostra funció inesperada.
Nota : una excepció de classe derivada s'ha de detectar abans d'una excepció de classe base.
Igual que Java, la biblioteca C++ té un excepció estàndard class que és la classe base per a totes les excepcions estàndard. Tots els objectes llançats pels components de la biblioteca estàndard es deriven d'aquesta classe. Per tant, es poden detectar totes les excepcions estàndard capturant aquest tipus.
Propietat 4
A diferència de Java, en C++, totes les excepcions estan desmarcades, és a dir, el compilador no verifica si s'ha detectat una excepció o no (vegeu això per als detalls). Per tant, no és necessari especificar totes les excepcions no detectades en una declaració de funció. Tanmateix, el maneig d'excepcions és una pràctica recomanada per fer-ho.
Exemple
El següent programa compila bé, però idealment, la signatura de fun() hauria d'enumerar les excepcions no marcades.
CPP
somriure més bonic
// 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;> }> |
>
>Sortida
Caught exception from fun()>
Una millor manera d'escriure el codi anterior:
CPP
// 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;> }> |
>
>Sortida
Caught exception from fun()>
Nota : L'ús de l'especificació d'excepció dinàmica ha quedat obsolet des de C++11. Una de les raons per això pot ser que pot avortar el vostre programa aleatòriament. Això pot passar quan llanceu una excepció d'un altre tipus que no s'esmenta a l'especificació d'excepció dinàmica. El vostre programa s'avortarà perquè, en aquest escenari, crida (indirectament) a terminate(), que per defecte crida a abort().
Propietat 5
En C++, els blocs try/catch es poden imbricar. A més, es pot tornar a llançar una excepció amb throw; .
Exemple
El programa següent mostra la nidificació de blocs try/catch.
CPP
// 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;> }> |
què és internet
>
>Sortida
Handle Partially Handle remaining>
Una funció també pot tornar a llançar una funció utilitzant el mateix llançament; sintaxi. Una funció pot gestionar una part i demanar a la persona que truca que gestioni la resta.
Propietat 6
Quan es llança una excepció, tots els objectes creats dins del bloc try que l'adjunta es destrueixen abans que el control es transfereixi al bloc catch.
Exemple
El programa següent mostra la propietat anterior.
CPP
// 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;> >}> }> |
>
>Sortida
Constructor of Test Destructor of Test Caught 10>
Limitacions del maneig d'excepcions en C++
El maneig d'excepcions en C++ també té algunes limitacions:
- Les excepcions poden trencar l'estructura o el flux del codi, ja que es creen diversos punts de sortida invisibles al codi, cosa que fa que el codi sigui difícil de llegir i depurar.
- Si el maneig d'excepcions no es fa correctament, també pot provocar fuites de recursos.
- És difícil aprendre a escriure un codi d'excepció que sigui segur.
- No hi ha cap estàndard C++ sobre com utilitzar el maneig d'excepcions, per tant existeixen moltes variacions en les pràctiques de maneig d'excepcions.
Conclusió
El maneig d'excepcions en C++ s'utilitza per gestionar els succeïts inesperats mitjançant blocs try and catch per gestionar el problema de manera eficient. Aquest maneig d'excepcions fa que els nostres programes siguin més fiables, ja que els errors en temps d'execució es poden gestionar per separat i també ajuda a evitar que el programa s'estavella i la finalització brusca del programa quan es produeix un error.
Articles relacionats:
- Principal Excepció C++ Gestió de preguntes i respostes d'entrevistes
- Test sobre el maneig d'excepcions en C++