V C++ sú výnimkou runtime anomálie alebo abnormálne podmienky, s ktorými sa program stretne počas svojho vykonávania. Proces spracovania týchto výnimiek sa nazýva spracovanie výnimiek. Pomocou mechanizmu spracovania výnimiek možno preniesť ovládanie z jednej časti programu, kde sa výnimka vyskytla, do inej časti kódu.
Takže v podstate pomocou spracovania výnimiek v C++ môžeme spracovať výnimky tak, aby náš program zostal spustený.
generátor náhodných čísel v c
Čo je výnimka C++?
Výnimkou je neočakávaný problém, ktorý vznikne počas vykonávania programu, náš program sa náhle ukončí s nejakými chybami/problémami. Výnimka nastáva počas behu programu (runtime).
Typy výnimiek C++
V C++ existujú dva typy výnimiek
- Synchrónne: Výnimky, ktoré sa stanú, keď sa niečo pokazí v dôsledku chyby vo vstupných údajoch alebo keď program nie je vybavený na spracovanie aktuálneho typu údajov, s ktorými pracuje, ako je napríklad delenie čísla nulou.
- Asynchrónne : Výnimky, ktoré sú mimo kontroly programu, ako napríklad zlyhanie disku, prerušenia klávesnice atď.
C++ skúste a chyťte
C++ poskytuje vstavanú funkciu pre spracovanie výnimiek. Dá sa to urobiť pomocou nasledujúcich špecializovaných kľúčových slov: skúšaj, chyť a hádž, pričom každé z nich má iný účel.
Syntax 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. skúste v C++
Kľúčové slovo try predstavuje blok kódu, ktorý môže vyvolať výnimku umiestnenú v bloku try. Po ňom nasleduje jeden alebo viac blokov úlovkov. Ak sa vyskytne výnimka, skúste túto výnimku zablokovať.
2. chytiť v C++
Príkaz catch predstavuje blok kódu, ktorý sa vykoná pri vyvolaní konkrétnej výnimky z bloku try. Kód na spracovanie výnimky je napísaný vo vnútri bloku catch.
3. nahodiť C++
Výnimku v C++ je možné vyvolať pomocou kľúčového slova throw. Keď program narazí na príkaz throw, okamžite ukončí aktuálnu funkciu a začne hľadať zodpovedajúci blok catch na spracovanie vyvolanej výnimky.
Poznámka: Na zachytenie rôznych typov výnimiek vyvolaných blokom try možno použiť viacero príkazov catch.
Kľúčové slová try and catch prichádzajú v pároch: Používame blok try na testovanie nejakého kódu a ak kód vyvolá výnimku, spracujeme ju v našom bloku catch.
Prečo potrebujeme Spracovanie výnimiek v C++?
Toto sú hlavné výhody spracovania výnimiek oproti tradičnému spracovaniu chýb:
- Oddelenie kódu spracovania chýb od normálneho kódu : Vždy existujú podmienky if-else na spracovanie chýb v tradičných kódoch spracovania chýb. Tieto podmienky a kód na spracovanie chýb sa zmiešajú s normálnym tokom. Vďaka tomu je kód menej čitateľný a udržiavateľný. Pomocou blokov try/catch sa kód na spracovanie chýb oddelí od normálneho toku.
- Funkcie/metódy dokážu spracovať iba výnimky, ktoré si vyberú : Funkcia môže vyvolať veľa výnimiek, ale môže sa rozhodnúť spracovať niektoré z nich. Ostatne vynimky, ktore sa vyhodia, ale nezachytia, vie vybavit volajuci. Ak sa volajúci rozhodne, že ich nezachytí, výnimky rieši volajúci volajúceho.
V C++ môže funkcia špecifikovať výnimky, ktoré vyvoláva, pomocou kľúčového slova throw. Volajúci tejto funkcie musí výnimku nejakým spôsobom spracovať (buď jej opätovným zadaním alebo zachytením).
- Zoskupovanie typov chýb : V C++ môžu byť ako výnimky vyvolané základné typy aj objekty. Môžeme vytvárať hierarchiu objektov výnimiek, zoskupovať výnimky v menných priestoroch alebo triedach a kategorizovať ich podľa ich typov.
Príklady spracovania výnimiek v C++
Nasledujúce príklady ukazujú, ako používať blok try-catch na spracovanie výnimiek v C++.
Príklad 1
Nižšie uvedený príklad demonštruje výnimky vyvolané 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;> }> |
>
>Výkon
Exception Division by zero not allowed!>
Príklad 2
Nasleduje jednoduchý príklad, ktorý ukazuje spracovanie výnimiek v C++. Výstup programu vysvetľuje tok vykonávania blokov 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;> }> |
>
>Výkon
Before try Inside try Exception Caught After catch (Will be executed)>
Vlastnosti spracovania výnimiek v C++
Nehnuteľnosť 1
Existuje špeciálny blok catch nazývaný blok „catch-all“, napísaný ako catch(…), ktorý možno použiť na zachytenie všetkých typov výnimiek.
Príklad
V nasledujúcom programe sa ako výnimka vyvolá int, ale pre int neexistuje blok catch, takže sa vykoná blok 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;> }> |
bash while loop
>
>Výkon
Default Exception>
Nehnuteľnosť 2
Konverzia implicitného typu sa nevyskytuje pri primitívnych typoch.
Príklad
V nasledujúcom programe nie je „a“ implicitne prevedené na 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;> }> |
>
>Výkon
Default Exception>
Výkon:
Default Exception>
Nehnuteľnosť 3
Ak je vyvolaná výnimka a nikde sa nezachytí, program sa nenormálne ukončí.
Príklad
V nasledujúcom programe je vyhodený znak, ale nie je tu žiadny blok na zachytenie znaku.
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;> }> |
>
>
Výkon
terminate called after throwing an instance of 'char'>
Toto abnormálne ukončovacie správanie môžeme zmeniť napísaním našej neočakávanej funkcie.
relačná algebra v rdbms
Poznámka : Výnimka odvodenej triedy by sa mala zachytiť pred výnimkou základnej triedy.
Rovnako ako Java, aj knižnica C++ má a štandardná výnimka trieda, ktorá je základnou triedou pre všetky štandardné výnimky. Všetky objekty vyvolané komponentmi štandardnej knižnice sú odvodené z tejto triedy. Chytaním tohto typu sa teda dajú zachytiť všetky štandardné výnimky.
Nehnuteľnosť 4
Na rozdiel od Java v C++ sú všetky výnimky nezačiarknuté, t.j. kompilátor nekontroluje, či je výnimka zachytená alebo nie (pozri toto pre podrobnosti). Takže nie je potrebné špecifikovať všetky nezachytené výnimky v deklarácii funkcie. Odporúčaný postup je však pri manipulácii s výnimkami.
Príklad
Nasledujúci program sa skompiluje dobre, ale v ideálnom prípade by signatúra fun() mala uvádzať nekontrolované výnimky.
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;> }> |
>
>Výkon
Caught exception from fun()>
Lepší spôsob, ako napísať vyššie uvedený kód:
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;> }> |
zoznam polí zoradený
>
>Výkon
Caught exception from fun()>
Poznámka : Používanie špecifikácie dynamických výnimiek bolo od C++11 zastarané. Jedným z dôvodov môže byť, že môže náhodne prerušiť váš program. To sa môže stať, keď vyvoláte výnimku iného typu, ktorý nie je uvedený v špecifikácii dynamickej výnimky. Váš program sa sám preruší, pretože v tomto scenári volá (nepriamo) termin(), ktorý štandardne volá abort().
Nehnuteľnosť 5
V C++ môžu byť bloky try/catch vnorené. Výnimku je možné znova vyvolať pomocou throw; .
Príklad
Nasledujúci program ukazuje vkladanie blokov pokusu/chytenia.
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;> }> |
>
>Výkon
Handle Partially Handle remaining>
Funkcia môže tiež znovu vyvolať funkciu pomocou rovnakého hodu; syntax. Funkcia môže spracovať časť a požiadať volajúceho, aby spracoval zvyšok.
Nehnuteľnosť 6
Keď je vyvolaná výnimka, všetky objekty vytvorené vo vnútri obklopujúceho bloku try sa zničia predtým, ako sa ovládací prvok prenesie do bloku catch.
Príklad
Nasledujúci program demonštruje vyššie uvedenú vlastnosť.
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;> >}> }> |
vlastnosti série panda
>
>Výkon
Constructor of Test Destructor of Test Caught 10>
Obmedzenia spracovania výnimiek v C++
Spracovanie výnimiek v C++ má tiež niekoľko obmedzení:
- Výnimky môžu narušiť štruktúru alebo tok kódu, pretože v kóde je vytvorených viacero neviditeľných výstupných bodov, čo sťažuje čítanie a ladenie kódu.
- Ak sa spracovanie výnimiek nevykonáva správne, môže to viesť aj k únikom zdrojov.
- Je ťažké naučiť sa písať kód výnimky, ktorý je bezpečný.
- Neexistuje žiadny štandard C++ o tom, ako používať spracovanie výnimiek, a preto existuje veľa variácií v postupoch spracovania výnimiek.
Záver
Spracovanie výnimiek v C++ sa používa na zvládnutie neočakávaných udalostí pomocou blokov try and catch na efektívne riadenie problému. Toto spracovanie výnimiek robí naše programy spoľahlivejšími, pretože chyby za behu je možné spracovať samostatne a tiež pomáha predchádzať zlyhaniu programu a náhlemu ukončeniu programu, keď sa vyskytne chyba.
Súvisiace články:
- Najlepšie otázky a odpovede na pohovore týkajúce sa spracovania výnimiek v jazyku C++
- Kvíz o spracovaní výnimiek v C++