logo

Unntakshåndtering i C++

I C++ er unntak kjøretidsavvik eller unormale forhold som et program møter under kjøringen. Prosessen med å håndtere disse unntakene kalles unntakshåndtering. Ved å bruke unntakshåndteringsmekanismen kan kontrollen fra en del av programmet der unntaket skjedde overføres til en annen del av koden.

Så ved å bruke unntakshåndtering i C++, kan vi håndtere unntakene slik at programmet fortsetter å kjøre.



noe rask sortering

Hva er et C++-unntak?

Et unntak er et uventet problem som oppstår under kjøringen av et program programmet vårt avsluttes plutselig med noen feil/problemer. Unntak oppstår under kjøring av programmet (runtime).

Typer C++-unntak

Det er to typer unntak i C++

  1. Synkron: Unntak som skjer når noe går galt på grunn av en feil i inndataene eller når programmet ikke er utstyrt for å håndtere gjeldende type data det jobber med, for eksempel å dele et tall med null.
  2. Asynkron : Unntak som er utenfor programmets kontroll, som diskfeil, tastaturavbrudd osv.

C++ prøv og fang

C++ gir en innebygd funksjon for unntakshåndtering. Det kan gjøres ved å bruke følgende spesialiserte nøkkelord: prøv, fang og kast med hvert sitt formål.



Syntaks for try-catch i 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. prøv i C++

Nøkkelordet try representerer en kodeblokk som kan gi et unntak plassert inne i try-blokken. Den etterfølges av en eller flere fangstblokker. Hvis et unntak oppstår, prøv å blokkere det unntaket.

2. fange i C++

Catch-setningen representerer en kodeblokk som utføres når et bestemt unntak blir kastet fra try-blokken. Koden for å håndtere unntaket er skrevet inne i catch-blokken.

3. kaste inn C++

Et unntak i C++ kan kastes ved å bruke søkeordet throw. Når et program møter en throw-setning, avslutter det umiddelbart gjeldende funksjon og begynner å finne en matchende catch-blokk for å håndtere det kastede unntaket.



Merk: Flere catch-setninger kan brukes til å fange opp forskjellige typer unntak som er kastet av try-blokk.

Nøkkelordene try and catch kommer i par: Vi bruker try-blokken for å teste noe kode, og hvis koden gir et unntak, vil vi håndtere det i catch-blokken vår.

Hvorfor trenger vi Unntakshåndtering i C++?

Følgende er hovedfordelene med unntakshåndtering fremfor tradisjonell feilhåndtering:

  1. Separasjon av feilhåndteringskode fra normal kode : Det er alltid if-else-betingelser for å håndtere feil i tradisjonelle feilhåndteringskoder. Disse forholdene og koden for å håndtere feil blandes sammen med den normale flyten. Dette gjør koden mindre lesbar og vedlikeholdbar. Med try/catch-blokker blir koden for feilhåndtering atskilt fra normal flyt.
  2. Funksjoner/metoder kan håndtere bare unntakene de velger : En funksjon kan gi mange unntak, men kan velge å håndtere noen av dem. De andre unntakene, som blir kastet, men ikke fanget opp, kan den som ringer håndtere. Hvis den som ringer velger å ikke fange dem, håndteres unntakene av den som ringer.
    I C++ kan en funksjon spesifisere unntakene den kaster ved å bruke nøkkelordet throw. Den som ringer denne funksjonen må håndtere unntaket på en eller annen måte (enten ved å spesifisere det på nytt eller fange det).
  3. Gruppering av feiltyper : I C++ kan både grunnleggende typer og objekter kastes som unntak. Vi kan lage et hierarki av unntaksobjekter, gruppere unntak i navneområder eller klasser, og kategorisere dem i henhold til deres typer.

Eksempler på unntakshåndtering i C++

Følgende eksempler viser hvordan du bruker en try-catch-blokk for å håndtere unntak i C++.

Eksempel 1

Eksemplet nedenfor viser kaste-unntak i 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;> }>

>

>

Produksjon

Exception Division by zero not allowed!>

Eksempel 2

Følgende er et enkelt eksempel for å vise unntakshåndtering i C++. Utdataene fra programmet forklarer flyten av utførelse av try/catch-blokker.

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

>

>

Produksjon

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

Egenskaper for unntakshåndtering i C++

Eiendom 1

Det er en spesiell catch-blokk kalt 'catch-all'-blokken, skrevet som catch(...), som kan brukes til å fange opp alle typer unntak.

Eksempel

I det følgende programmet blir en int kastet som et unntak, men det er ingen catch-blokk for int, så catch(...)-blokken vil bli utført.

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

>

>

hvordan konvertere int til streng java
Produksjon

Default Exception>

Eiendom 2

Implisitt typekonvertering skjer ikke for primitive typer.

Eksempel

I det følgende programmet er 'a' ikke implisitt konvertert til 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;> }>

>

>

Produksjon

Default Exception>

Produksjon:

Default Exception>

Eiendom 3

Hvis et unntak blir kastet og ikke fanget opp noe sted, avsluttes programmet unormalt.

Eksempel

I det følgende programmet kastes en røye, men det er ingen fangstblokk for å fange røye.

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

>

>

Produksjon

terminate called after throwing an instance of 'char'>

Vi kan endre denne unormale oppsigelsesadferden ved å skrive vår uventede funksjon.

Merk : Et avledet klasseunntak bør fanges opp før et grunnklasseunntak.

I likhet med Java har C++-biblioteket en standard unntak klasse som er basisklassen for alle standard unntak. Alle objekter som kastes av komponentene i standardbiblioteket er avledet fra denne klassen. Derfor kan alle standard unntak fanges opp ved å fange denne typen.

Eiendom 4

I motsetning til Java, i C++, er alle unntak avmerket, dvs. kompilatoren sjekker ikke om et unntak er fanget eller ikke (se dette for detaljer). Så det er ikke nødvendig å spesifisere alle ufangede unntak i en funksjonserklæring. Imidlertid er unntakshåndtering en anbefalt praksis å gjøre det.

Eksempel

hvor mange null for en million

Følgende program kompilerer fint, men ideelt sett bør signaturen til fun() vise de ukontrollerte unntakene.

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

>

>

hvor stor er skjermen min
Produksjon

Caught exception from fun()>

En bedre måte å skrive koden ovenfor på:

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

>

>

Produksjon

Caught exception from fun()>

Merk : Bruken av Dynamic Exception Specification har blitt avviklet siden C++11. En av grunnene til det kan være at det tilfeldig kan avbryte programmet ditt. Dette kan skje når du kaster et unntak av en annen type som ikke er nevnt i den dynamiske unntaksspesifikasjonen. Programmet ditt vil avbryte seg selv fordi det i det scenariet kaller (indirekte) terminate(), som som standard kaller abort().

Eiendom 5

I C++ kan try/catch-blokker nestes. Et unntak kan også kastes på nytt ved å bruke kast; .

Eksempel

Følgende program viser try/catch-blokker som hekker.

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

>

>

Produksjon

Handle Partially Handle remaining>

En funksjon kan også kaste en funksjon på nytt ved å bruke samme kast; syntaks. En funksjon kan håndtere en del og be den som ringer om å håndtere det resterende.

Eiendom 6

Når et unntak blir kastet, blir alle objekter som er opprettet inne i den omsluttende prøveblokken ødelagt før kontrollen overføres til catch-blokken.

Eksempel

Følgende program demonstrerer egenskapen ovenfor.

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

>

>

nettverk og typer nettverk
Produksjon

Constructor of Test Destructor of Test Caught 10>

Begrensninger for unntakshåndtering i C++

Unntakshåndteringen i C++ har også få begrensninger:

  • Unntak kan bryte strukturen eller flyten til koden ettersom flere usynlige utgangspunkter opprettes i koden som gjør koden vanskelig å lese og feilsøke.
  • Hvis unntakshåndtering ikke gjøres riktig, kan det også føre til ressurslekkasjer.
  • Det er vanskelig å lære å skrive unntakskode som er trygg.
  • Det er ingen C++-standard for hvordan man bruker unntakshåndtering, derfor finnes det mange variasjoner i praksis for unntakshåndtering.

Konklusjon

Unntakshåndtering i C++ brukes til å håndtere uventede hendelser ved å bruke try and catch-blokker for å håndtere problemet effektivt. Denne unntakshåndteringen gjør programmene våre mer pålitelige ettersom feil under kjøring kan håndteres separat, og det bidrar også til å forhindre at programmet krasjer og brå avslutning av programmet når det oppstår feil.

Relaterte artikler:

  • Topp C++ unntakshåndtering intervjuspørsmål og svar
  • Quiz om unntakshåndtering i C++