În C++, excepțiile sunt anomalii de rulare sau condiții anormale pe care le întâlnește un program în timpul execuției sale. Procesul de gestionare a acestor excepții se numește gestionarea excepțiilor. Folosind mecanismul de gestionare a excepțiilor, controlul dintr-o parte a programului în care a avut loc excepția poate fi transferat într-o altă parte a codului.
Deci, practic, folosind gestionarea excepțiilor în C++, putem gestiona excepțiile astfel încât programul nostru să continue să ruleze.
cartonată vs broșată
Ce este o excepție C++?
O excepție este o problemă neașteptată care apare în timpul execuției unui program programul nostru se încheie brusc cu unele erori/probleme. Excepția apare în timpul rulării programului (runtime).
Tipuri de excepție C++
Există două tipuri de excepții în C++
- Sincron: Excepții care se întâmplă atunci când ceva nu merge bine din cauza unei greșeli în datele de intrare sau când programul nu este echipat să gestioneze tipul curent de date cu care lucrează, cum ar fi împărțirea unui număr la zero.
- Asincron : Excepții care sunt în afara controlului programului, cum ar fi defecțiunea discului, întreruperile de la tastatură etc.
C++ încearcă și prinde
C++ oferă o caracteristică încorporată pentru gestionarea excepțiilor. Se poate face folosind următoarele cuvinte cheie specializate: încercați, prindeți și aruncați, fiecare având un scop diferit.
Sintaxa lui try-catch în 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. încercați în C++
Cuvântul cheie try reprezintă un bloc de cod care poate arunca o excepție plasată în blocul try. Este urmat de unul sau mai multe blocuri de captură. Dacă apare o excepție, încercați să blocați acea excepție.
2. prinde în C++
Declarația catch reprezintă un bloc de cod care este executat atunci când o anumită excepție este aruncată din blocul try. Codul care gestionează excepția este scris în blocul catch.
3. introduceți C++
O excepție în C++ poate fi aruncată folosind cuvântul cheie throw. Când un program întâlnește o instrucțiune throw, apoi oprește imediat funcția curentă și începe să găsească un bloc catch potrivit pentru a gestiona excepția aruncată.
Notă: Mai multe instrucțiuni catch pot fi folosite pentru a prinde diferite tipuri de excepții aruncate de blocul try.
Cuvintele cheie try and catch vin în perechi: folosim blocul try pentru a testa un cod și dacă codul aruncă o excepție, o vom gestiona în blocul nostru catch.
De ce avem nevoie Gestionarea excepțiilor în C++?
Următoarele sunt principalele avantaje ale gestionării excepțiilor față de gestionarea tradițională a erorilor:
- Separarea codului de tratare a erorilor de codul normal : Există întotdeauna condiții dacă-altfel pentru a gestiona erorile în codurile tradiționale de tratare a erorilor. Aceste condiții și codul de gestionare a erorilor se amestecă cu fluxul normal. Acest lucru face codul mai puțin lizibil și mai ușor de întreținut. Cu blocurile try/catch, codul pentru gestionarea erorilor devine separat de fluxul normal.
- Funcțiile/Metodele pot gestiona doar excepțiile pe care le aleg : O funcție poate arunca multe excepții, dar poate alege să gestioneze unele dintre ele. Celelalte excepții, care sunt aruncate, dar nu prinse, pot fi gestionate de apelant. Dacă apelantul alege să nu-i prindă, atunci excepțiile sunt gestionate de apelantul apelantului.
În C++, o funcție poate specifica excepțiile pe care le aruncă folosind cuvântul cheie throw. Apelantul acestei funcții trebuie să gestioneze excepția într-un fel (fie specificând-o din nou, fie prinzând-o).
- Gruparea tipurilor de erori : În C++, atât tipurile de bază, cât și obiectele pot fi aruncate ca excepții. Putem crea o ierarhie de obiecte de excepție, grupăm excepțiile în spații de nume sau clase și le putem clasifica în funcție de tipurile lor.
Exemple de tratare a excepțiilor în C++
Următoarele exemple demonstrează cum să utilizați un bloc try-catch pentru a gestiona excepțiile în C++.
Exemplul 1
Exemplul de mai jos demonstrează aruncarea excepțiilor în 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;> }> |
>
>Ieșire
Exception Division by zero not allowed!>
Exemplul 2
Următorul este un exemplu simplu pentru a arăta gestionarea excepțiilor în C++. Ieșirea programului explică fluxul de execuție al blocurilor 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;> }> |
>
>Ieșire
Before try Inside try Exception Caught After catch (Will be executed)>
Proprietăți ale gestionării excepțiilor în C++
Proprietatea 1
Există un bloc catch special numit blocul „catch-all”, scris catch(…), care poate fi folosit pentru a prinde toate tipurile de excepții.
Exemplu
În programul următor, un int este aruncat ca excepție, dar nu există un bloc catch pentru int, așa că blocul catch(…) va fi executat.
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;> }> |
>
>Ieșire
Default Exception>
Proprietatea 2
Conversia implicită a tipurilor nu are loc pentru tipurile primitive.
Exemplu
În programul următor, „a” nu este convertit implicit în int.
CPP
gimp cum să deselectezi
//// 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;> }> |
>
>
modifica fișierul linuxIeșire
Default Exception>
Ieșire:
Default Exception>
Proprietatea 3
Dacă o excepție este aruncată și nu este prinsă nicăieri, programul se termină anormal.
Exemplu
În programul următor, un caracter este aruncat, dar nu există un bloc catch pentru a prinde caracterul.
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;> }> |
>
>
Ieșire
terminate called after throwing an instance of 'char'>
Putem schimba acest comportament anormal de terminare scriind funcția noastră neașteptată.
Notă : O excepție de clasă derivată ar trebui să fie capturată înaintea unei excepții de clasă de bază.
La fel ca Java, biblioteca C++ are un excepție standard clasa care este clasa de bază pentru toate excepțiile standard. Toate obiectele aruncate de componentele bibliotecii standard sunt derivate din această clasă. Prin urmare, toate excepțiile standard pot fi prinse prin capturarea acestui tip.
Proprietatea 4
Spre deosebire de Java, în C++, toate excepțiile sunt nebifate, adică compilatorul nu verifică dacă o excepție este capturată sau nu (vezi acest pentru detalii). Deci, nu este necesar să specificați toate excepțiile neprinse într-o declarație de funcție. Cu toate acestea, gestionarea excepțiilor este o practică recomandată.
Exemplu
Următorul program compilează bine, dar în mod ideal, semnătura fun() ar trebui să enumere excepțiile nebifate.
CPP
javascript onclick
// 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;> }> |
>
>Ieșire
Caught exception from fun()>
O modalitate mai bună de a scrie codul de mai sus:
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;> }> |
>
>Ieșire
Caught exception from fun()>
Notă : Utilizarea specificației Dynamic Exception a fost retrasă din C++11. Unul dintre motivele pentru aceasta poate fi acela că vă poate anula aleatoriu programul. Acest lucru se poate întâmpla atunci când aruncați o excepție de alt tip care nu este menționată în specificația excepției dinamice. Programul dvs. se va anula deoarece, în acel scenariu, apelează (indirect) terminate(), care în mod implicit apelează abort().
Proprietatea 5
În C++, blocurile try/catch pot fi imbricate. De asemenea, o excepție poate fi re-arunsă folosind throw; .
Exemplu
Următorul program arată imbricarea blocurilor try/catch.
CPP
javascript onclick
// 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;> }> |
>
>Ieșire
Handle Partially Handle remaining>
O funcție poate, de asemenea, re-arunca o funcție folosind aceeași aruncare; sintaxă. O funcție poate gestiona o parte și poate cere apelantului să se ocupe de restul.
Proprietatea 6
Când se aruncă o excepție, toate obiectele create în interiorul blocului de încercare care înconjoară sunt distruse înainte ca controlul să fie transferat în blocul catch.
Exemplu
Următorul program demonstrează proprietatea de mai sus.
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;> >}> }> |
>
>Ieșire
Constructor of Test Destructor of Test Caught 10>
Limitări ale gestionării excepțiilor în C++
Gestionarea excepțiilor în C++ are, de asemenea, câteva limitări:
- Excepțiile pot rupe structura sau fluxul codului, deoarece în cod sunt create mai multe puncte de ieșire invizibile, ceea ce face codul greu de citit și de depanat.
- Dacă gestionarea excepțiilor nu este făcută corect, poate duce și la scurgeri de resurse.
- Este greu să înveți cum să scrii un cod de excepție care este sigur.
- Nu există un standard C++ cu privire la modul de utilizare a gestionării excepțiilor, prin urmare există multe variații în practicile de gestionare a excepțiilor.
Concluzie
Gestionarea excepțiilor în C++ este folosită pentru a gestiona întâmplările neașteptate folosind blocurile try and catch pentru a gestiona problema eficient. Această gestionare a excepțiilor face ca programele noastre să fie mai fiabile, deoarece erorile în timpul execuției pot fi gestionate separat și, de asemenea, ajută la prevenirea prăbușirii programului și a opririi bruște a programului atunci când se întâlnește o eroare.
Articole similare:
- Top C++ Excepție care gestionează întrebări și răspunsuri la interviu
- Test despre gestionarea excepțiilor în C++