logo

Obravnava izjem v C++

V C++ so izjeme anomalije med izvajanjem ali nenormalni pogoji, na katere program naleti med svojim izvajanjem. Postopek obravnavanja teh izjem se imenuje obravnavanje izjem. Z uporabo mehanizma za obravnavo izjem se lahko nadzor iz enega dela programa, kjer je prišlo do izjeme, prenese na drug del kode.

Tako lahko v bistvu z uporabo obravnavanja izjem v C++ obravnavamo izjeme, tako da se naš program še naprej izvaja.



različice za android

Kaj je izjema C++?

Izjema je nepričakovana težava, ki se pojavi med izvajanjem programa. Naš program se nenadoma prekine z nekaterimi napakami/težavami. Izjema se pojavi med izvajanjem programa (runtime).

Vrste izjem C++

V C++ obstajata dve vrsti izjem

  1. sinhrono: Izjeme, ki se zgodijo, ko gre kaj narobe zaradi napake v vhodnih podatkih ali ko program ni opremljen za obravnavo trenutne vrste podatkov, s katerimi dela, kot je deljenje števila z ničlo.
  2. Asinhrono : Izjeme, ki so izven nadzora programa, kot so okvara diska, prekinitve tipkovnice itd.

C++ poskusi in ulovi

C++ ponuja vgrajeno funkcijo za obravnavanje izjem. To je mogoče storiti z uporabo naslednjih specializiranih ključnih besed: poskusi, ulovi in ​​vrzi, pri čemer ima vsaka drugačen namen.



Sintaksa try-catch v 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. poskusi v C++

Ključna beseda try predstavlja blok kode, ki lahko vrže izjemo znotraj bloka try. Sledi mu en ali več ulovnih blokov. Če pride do izjeme, poskusite blokirati to izjemo.

2. catch v C++

Stavek catch predstavlja blok kode, ki se izvede, ko je določena izjema vržena iz bloka poskusa. Koda za obravnavo izjeme je zapisana znotraj bloka catch.

3. dodamo C++

Izjema v C++ se lahko vrže s ključno besedo throw. Ko program naleti na stavek vrženja, takoj prekine trenutno funkcijo in začne iskati ustrezen blok catch za obravnavo vržene izjeme.



Opomba: Več stavkov catch je mogoče uporabiti za lovljenje različnih vrst izjem, ki jih vrže blok poskusa.

Ključni besedi poskusi in ulovi sta na voljo v parih: blok poskusa uporabljamo za testiranje neke kode in če koda vrže izjemo, jo bomo obravnavali v bloku catch.

Zakaj potrebujemo Obravnava izjem v C++?

Sledijo glavne prednosti obravnavanja izjem pred tradicionalnim obravnavanjem napak:

  1. Ločevanje kode za obravnavo napak od običajne kode : V tradicionalnih kodah za obravnavo napak vedno obstajajo pogoji if-else za obravnavo napak. Ti pogoji in koda za obravnavanje napak se pomešajo z običajnim tokom. Zaradi tega je koda manj berljiva in manj vzdržljiva. Z bloki try/catch postane koda za obravnavanje napak ločena od običajnega toka.
  2. Funkcije/metode lahko obravnavajo samo izjeme, ki jih izberejo : Funkcija lahko povzroči številne izjeme, vendar se lahko odloči, da bo obravnavala nekatere od njih. Druge izjeme, ki so vržene, a ne ulovljene, lahko obravnava klicatelj. Če se klicatelj odloči, da jih ne ujame, potem izjeme obravnava klicatelj klicatelja.
    V C++ lahko funkcija določi izjeme, ki jih vrže s ključno besedo throw. Klicatelj te funkcije mora na nek način ravnati z izjemo (bodisi jo znova določiti ali jo ujeti).
  3. Združevanje vrst napak : V C++ se lahko kot izjeme vržejo tako osnovni tipi kot objekti. Ustvarimo lahko hierarhijo objektov izjem, združimo izjeme v imenske prostore ali razrede in jih kategoriziramo glede na njihove vrste.

Primeri obravnavanja izjem v C++

Naslednji primeri prikazujejo, kako uporabiti blok try-catch za obravnavanje izjem v C++.

Primer 1

Spodnji primer prikazuje vržene izjeme v 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;> }>

>

>

Izhod

Exception Division by zero not allowed!>

Primer 2

Sledi preprost primer za prikaz obravnave izjem v C++. Izhod programa pojasnjuje potek izvajanja blokov poskusi/ulovi.

CPP




t flip flop

// 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;> }>

>

>

Izhod

Before try Inside try Exception Caught After catch (Will be executed)>

Lastnosti obravnave izjem v C++

Lastnost 1

Obstaja poseben blok catch, imenovan blok 'catch-all', zapisan kot catch(...), ki se lahko uporablja za lovljenje vseh vrst izjem.

Primer

V naslednjem programu je int vržen kot izjema, vendar za int ni bloka catch, zato bo blok catch(…) izveden.

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

>

>

Izhod

Default Exception>

Lastnost 2

Implicitna pretvorba tipa se ne zgodi za primitivne tipe.

Primer

V naslednjem programu 'a' ni implicitno pretvorjen v 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;> }>

>

>

Izhod

dodajanje v polje java
Default Exception>

Izhod:

Default Exception>

Nepremičnina 3

Če pride do izjeme in ni nikjer ujet, se program nenormalno zaključi.

Primer

V naslednjem programu je vržen char, vendar ni bloka catch, ki bi ujel char.

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

>

>

Izhod

terminate called after throwing an instance of 'char'>

To nenormalno prekinitveno vedenje lahko spremenimo tako, da napišemo našo nepričakovano funkcijo.

Opomba : Izjema izpeljanega razreda je treba ujeti pred izjemo osnovnega razreda.

Tako kot Java ima tudi knjižnica C++ a standardna izjema razred, ki je osnovni razred za vse standardne izjeme. Vsi objekti, ki jih vržejo komponente standardne knjižnice, izhajajo iz tega razreda. Zato je mogoče vse standardne izjeme ujeti s tem tipom.

Lastnina 4

Za razliko od Jave so v C++ vse izjeme nepreverjene, kar pomeni, da prevajalnik ne preveri, ali je izjema ujeta ali ne (glejte to za podrobnosti). Torej ni treba podati vseh neulovljenih izjem v deklaraciji funkcije. Vendar pa je obravnavanje izjem priporočena praksa.

Primer

Naslednji program se dobro prevaja, vendar bi bilo idealno, če bi podpis funkcije fun() navedel nepreverjene izjeme.

CPP




// 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;> }>

>

>

Izhod

Caught exception from fun()>

Boljši način za pisanje zgornje kode:

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

>

>

tipkopisni datum
Izhod

Caught exception from fun()>

Opomba : Uporaba specifikacije dinamične izjeme je od C++11 opuščena. Eden od razlogov za to je lahko ta, da lahko naključno prekine vaš program. To se lahko zgodi, ko vržete izjemo druge vrste, ki ni omenjena v specifikaciji dinamične izjeme. Vaš program se bo sam prekinil, ker v tem scenariju kliče (posredno) terminate(), ki privzeto kliče abort().

Lastnina 5

V C++ so lahko bloki try/catch ugnezdeni. Prav tako je mogoče ponovno vrniti izjemo z uporabo throw; .

Primer

Naslednji program prikazuje gnezdenje blokov try/catch.

CPP




concat nizi 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;> }>

>

>

Izhod

Handle Partially Handle remaining>

Funkcija lahko tudi ponovno vrže funkcijo z istim vrženjem; sintaksa. Funkcija lahko obravnava del in zahteva od klicatelja, da obravnava preostali del.

Lastnina 6

Ko je vržena izjema, so vsi objekti, ustvarjeni znotraj obdajajočega poskusnega bloka, uničeni, preden se nadzor prenese na blok catch.

Primer

Naslednji program prikazuje zgornjo lastnost.

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

>

>

Izhod

Constructor of Test Destructor of Test Caught 10>

Omejitve obravnavanja izjem v C++

Obravnava izjem v C++ ima tudi nekaj omejitev:

  • Izjeme lahko porušijo strukturo ali potek kode, saj je v kodi ustvarjenih več nevidnih izhodnih točk, zaradi česar je kodo težko brati in odpravljati napake.
  • Če obdelava izjem ni izvedena pravilno, lahko povzroči tudi uhajanje virov.
  • Težko se je naučiti pisati kodo izjeme, ki je varna.
  • Za uporabo obravnave izjem ni standarda C++, zato obstajajo številne različice praks obravnave izjem.

Zaključek

Obravnava izjem v C++ se uporablja za obravnavo nepričakovanih dogodkov z uporabo blokov poskusi in ulovi za učinkovito obvladovanje težave. Zaradi tega obravnavanja izjem so naši programi bolj zanesljivi, saj je mogoče napake med izvajanjem obravnavati ločeno, pomaga pa tudi preprečiti zrušitev programa in nenadno prekinitev programa, ko pride do napake.

Povezani članki:

  • Najboljša vprašanja in odgovori za intervjuje za obravnavanje izjem C++
  • Kviz o obravnavanju izjem v C++