logo

Undtagelseshåndtering i C++

I C++ er undtagelser runtime-anomalier eller unormale forhold, som et program støder på under dets udførelse. Processen med at håndtere disse undtagelser kaldes undtagelseshåndtering. Ved at bruge undtagelseshåndteringsmekanismen kan kontrollen fra en del af programmet, hvor undtagelsen opstod, overføres til en anden del af koden.

Så grundlæggende ved at bruge undtagelseshåndtering i C++, kan vi håndtere undtagelserne, så vores program bliver ved med at køre.



række af array i c

Hvad er en C++ undtagelse?

En undtagelse er et uventet problem, der opstår under udførelsen af ​​et program, vores program afsluttes pludseligt med nogle fejl/problemer. Undtagelse opstår under afviklingen af ​​programmet (runtime).

Typer af C++ undtagelser

Der er to typer undtagelser i C++

  1. Synkron: Undtagelser, der sker, når noget går galt på grund af en fejl i inputdata, eller når programmet ikke er udstyret til at håndtere den aktuelle type data, det arbejder med, såsom at dividere et tal med nul.
  2. Asynkron : Undtagelser, der er uden for programmets kontrol, såsom diskfejl, tastaturafbrydelser osv.

C++ prøv og fang

C++ giver en indbygget funktion til undtagelseshåndtering. Det kan gøres ved at bruge følgende specialiserede søgeord: prøv, fang og kast, med hver deres 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øgleordet try repræsenterer en kodeblok, der kan kaste en undtagelse placeret inde i try-blokken. Det efterfølges af en eller flere catch-blokke. Hvis der opstår en undtagelse, prøv at blokere den undtagelse.

2. fange i C++

Catch-sætningen repræsenterer en kodeblok, der udføres, når en bestemt undtagelse kastes fra try-blokken. Koden til at håndtere undtagelsen er skrevet inde i catch-blokken.

3. smid C++ ind

En undtagelse i C++ kan kastes ved at bruge søgeordet throw. Når et program støder på en throw-sætning, afslutter det øjeblikkeligt den aktuelle funktion og begynder at finde en matchende catch-blok til at håndtere den kastede undtagelse.



Bemærk: Flere catch-udsagn kan bruges til at fange forskellige typer undtagelser, der er kastet af try-blok.

Prøv og fang søgeord kommer i par: Vi bruger prøve-blokken til at teste noget kode, og hvis koden giver en undtagelse, håndterer vi det i vores catch-blok.

Hvorfor har vi brug for Undtagelseshåndtering i C++?

Følgende er de vigtigste fordele ved undtagelseshåndtering i forhold til traditionel fejlhåndtering:

  1. Adskillelse af fejlhåndteringskode fra normal kode : Der er altid if-else-betingelser for at håndtere fejl i traditionelle fejlhåndteringskoder. Disse forhold og koden til at håndtere fejl bliver blandet sammen med det normale flow. Dette gør koden mindre læsbar og vedligeholdelig. Med try/catch-blokke bliver koden til fejlhåndtering adskilt fra det normale flow.
  2. Funktioner/metoder kan kun håndtere de undtagelser, de vælger : En funktion kan give mange undtagelser, men kan vælge at håndtere nogle af dem. De andre undtagelser, som kastes, men ikke fanges, kan den, der ringer, håndtere. Hvis den, der ringer, vælger ikke at fange dem, håndteres undtagelserne af den, der ringer op.
    I C++ kan en funktion specificere de undtagelser, den kaster ved hjælp af nøgleordet throw. Den, der ringer til denne funktion, skal håndtere undtagelsen på en eller anden måde (enten ved at angive den igen eller fange den).
  3. Gruppering af fejltyper : I C++ kan både grundlæggende typer og objekter kastes som undtagelser. Vi kan oprette et hierarki af undtagelsesobjekter, gruppere undtagelser i navneområder eller klasser og kategorisere dem efter deres typer.

Eksempler på undtagelseshåndtering i C++

De følgende eksempler viser, hvordan man bruger en try-catch-blok til at håndtere undtagelser i C++.

Eksempel 1

Nedenstående eksempel viser throw-undtagelser 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;> }>

>

>

Produktion

Exception Division by zero not allowed!>

Eksempel 2

Det følgende er et simpelt eksempel til at vise undtagelseshåndtering i C++. Udgangen af ​​programmet forklarer strømmen af ​​udførelse af try/catch-blokke.

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

>

>

Produktion

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

Egenskaber for undtagelseshåndtering i C++

Ejendom 1

Der er en speciel catch-blok kaldet 'catch-all'-blokken, skrevet som catch(...), som kan bruges til at fange alle typer undtagelser.

Eksempel

I det følgende program kastes en int som en undtagelse, men der er ingen catch-blok for int, så catch(...)-blokken vil blive udfø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;> }>

>

>

forskel i python
Produktion

Default Exception>

Ejendom 2

Implicit typekonvertering sker ikke for primitive typer.

Eksempel

I det følgende program er 'a' ikke implicit konverteret 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;> }>

>

>

Produktion

Default Exception>

Produktion:

Default Exception>

Ejendom 3

Hvis en undtagelse bliver kastet og ikke fanget nogen steder, afsluttes programmet unormalt.

Eksempel

I det følgende program kastes en ør, men der er ingen fangblok til at fange øringen.

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

>

>

Produktion

terminate called after throwing an instance of 'char'>

Vi kan ændre denne unormale opsigelsesadfærd ved at skrive vores uventede funktion.

Bemærk : En afledt klasseundtagelse skal fanges før en basisklasseundtagelse.

Ligesom Java har C++-biblioteket en standard undtagelse klasse, som er basisklassen for alle standardundtagelser. Alle objekter kastet af komponenterne i standardbiblioteket er afledt fra denne klasse. Derfor kan alle standardundtagelser fanges ved at fange denne type.

Ejendom 4

I modsætning til Java er alle undtagelser i C++ ikke markeret, dvs. compileren kontrollerer ikke, om en undtagelse er fanget eller ej (se det her for detaljer). Så det er ikke nødvendigt at angive alle ufangede undtagelser i en funktionserklæring. Dog er det en anbefalet praksis at gøre det ved undtagelseshåndtering.

Eksempel

preg_match

Det følgende program kompilerer fint, men ideelt set bør signaturen for fun() angive de umarkerede undtagelser.

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

>

>

d flip flop
Produktion

Caught exception from fun()>

En bedre måde at skrive ovenstående kode 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;> }>

>

>

Produktion

Caught exception from fun()>

Bemærk : Brugen af ​​Dynamic Exception Specification er blevet forældet siden C++11. En af grundene til det kan være, at det tilfældigt kan afbryde dit program. Dette kan ske, når du kaster en undtagelse af en anden type, som ikke er nævnt i den dynamiske undtagelsesspecifikation. Dit program vil afbryde sig selv, fordi det i det scenarie kalder (indirekte) terminate(), som som standard kalder abort().

Ejendom 5

I C++ kan try/catch-blokke indlejres. En undtagelse kan også kastes igen ved at bruge throw; .

Eksempel

Følgende program viser indlejring af try/catch-blokke.

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

>

>

Produktion

Handle Partially Handle remaining>

En funktion kan også genkaste en funktion ved at bruge det samme kast; syntaks. En funktion kan håndtere en del og bede den, der ringer om at håndtere det resterende.

Ejendom 6

Når en undtagelse kastes, bliver alle objekter, der er oprettet inde i den omsluttende prøveblok, ødelagt, før kontrollen overføres til catch-blokken.

Eksempel

Følgende program demonstrerer ovenstående egenskab.

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

>

>

hvordan man konverterer en streng til en int
Produktion

Constructor of Test Destructor of Test Caught 10>

Begrænsninger af undtagelseshåndtering i C++

Undtagelseshåndteringen i C++ har også få begrænsninger:

  • Undtagelser kan bryde strukturen eller flowet af koden, da der oprettes flere usynlige udgangspunkter i koden, hvilket gør koden svær at læse og fejlsøge.
  • Hvis undtagelseshåndtering ikke udføres korrekt, kan det også føre til ressourcelækager.
  • Det er svært at lære at skrive undtagelseskode, der er sikker.
  • Der er ingen C++-standard for, hvordan man bruger undtagelseshåndtering, og derfor findes der mange variationer i praksis for håndtering af undtagelser.

Konklusion

Undtagelseshåndtering i C++ bruges til at håndtere uventede hændelser ved at bruge try and catch-blokke til at håndtere problemet effektivt. Denne undtagelseshåndtering gør vores programmer mere pålidelige, da fejl under kørsel kan håndteres separat, og det hjælper også med at forhindre, at programmet går ned og pludselig afslutter programmet, når der opstår fejl.

Relaterede artikler:

  • Top C++ undtagelseshåndtering interviewspørgsmål og svar
  • Quiz om undtagelseshåndtering i C++