V C++ jsou výjimkou anomálie za běhu nebo abnormální podmínky, se kterými se program setká během svého provádění. Proces zpracování těchto výjimek se nazývá zpracování výjimek. Pomocí mechanismu zpracování výjimek lze přenést ovládání z jedné části programu, kde k výjimce došlo, do jiné části kódu.
Takže v podstatě pomocí zpracování výjimek v C++ můžeme zpracovat výjimky, takže náš program běží dál.
kandidátský klíč
Co je výjimka C++?
Výjimkou je neočekávaný problém, který nastane během provádění programu, náš program se náhle ukončí s nějakými chybami/problémy. Výjimka nastává během běhu programu (runtime).
Typy výjimek C++
V C++ existují dva typy výjimek
- Synchronní: Výjimky, ke kterým dochází, když se něco pokazí kvůli chybě ve vstupních datech nebo když program není vybaven ke zpracování aktuálního typu dat, se kterými pracuje, jako je dělení čísla nulou.
- Asynchronní : Výjimky, které jsou mimo kontrolu programu, jako je selhání disku, přerušení klávesnice atd.
C++ zkuste a chytněte
C++ poskytuje vestavěnou funkci pro zpracování výjimek. To lze provést pomocí následujících specializovaných klíčových slov: zkuste, chyťte a házejte, přičemž každé z nich má jiný účel.
Syntaxe 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. zkuste v C++
Klíčové slovo try představuje blok kódu, který může vyvolat výjimku umístěnou uvnitř bloku try. Po něm následuje jeden nebo více chytacích bloků. Pokud dojde k výjimce, zkuste blokovat tuto výjimku.
2. chytit v C++
Příkaz catch představuje blok kódu, který se provede, když je vyvolána konkrétní výjimka z bloku try. Kód pro zpracování výjimky je zapsán uvnitř bloku catch.
3. hodit do C++
Výjimku v C++ lze vyvolat pomocí klíčového slova throw. Když program narazí na příkaz throw, okamžitě ukončí aktuální funkci a začne hledat odpovídající blok catch, aby zpracoval vyvolanou výjimku.
Poznámka: Více příkazů catch lze použít k zachycení různých typů výjimek vyvolaných blokem try.
Klíčová slova try and catch se vyskytují ve dvojicích: Blok try používáme k testování nějakého kódu a pokud kód vyvolá výjimku, zpracujeme ji v našem bloku catch.
Proč potřebujeme Zpracování výjimek v C++?
Níže jsou uvedeny hlavní výhody zpracování výjimek oproti tradičnímu zpracování chyb:
- Oddělení kódu zpracování chyb od normálního kódu : Vždy existují podmínky if-else pro zpracování chyb v tradičních kódech pro zpracování chyb. Tyto podmínky a kód pro zpracování chyb se zaměňují s normálním tokem. Díky tomu je kód méně čitelný a udržovatelný. S bloky try/catch se kód pro zpracování chyb oddělí od normálního toku.
- Funkce/Metody mohou zpracovávat pouze výjimky, které si vyberou : Funkce může vyvolat mnoho výjimek, ale může se rozhodnout zpracovat některé z nich. Ostatní výjimky, které jsou vyhozeny, ale nejsou zachyceny, může zpracovat volající. Pokud se volající rozhodne, že je nezachytí, pak výjimky řeší volající volajícího.
V C++ může funkce určit výjimky, které vyvolá, pomocí klíčového slova throw. Volající této funkce musí výjimku nějakým způsobem ošetřit (buď ji znovu specifikovat nebo ji zachytit).
- Seskupování typů chyb : V C++ mohou být jako výjimky vyvolány základní typy i objekty. Můžeme vytvořit hierarchii objektů výjimek, seskupit výjimky ve jmenných prostorech nebo třídách a kategorizovat je podle jejich typů.
Příklady zpracování výjimek v C++
Následující příklady ukazují, jak používat blok try-catch ke zpracování výjimek v C++.
Příklad 1
Níže uvedený příklad ukazuje výjimky vyvolání 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ýstup
Exception Division by zero not allowed!>
Příklad 2
Následuje jednoduchý příklad, který ukazuje zpracování výjimek v C++. Výstup programu vysvětluje tok provádění bloků 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ýstup
Before try Inside try Exception Caught After catch (Will be executed)>
Vlastnosti zpracování výjimek v C++
Nemovitost 1
Existuje speciální blok catch nazvaný blok „catch-all“, napsaný jako catch(…), který lze použít k zachycení všech typů výjimek.
Příklad
V následujícím programu se jako výjimka vyvolá int, ale pro int není žádný blok catch, takže se provede 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;> }> |
>
>Výstup
Default Exception>
Nemovitost 2
Konverze implicitního typu u primitivních typů neprobíhá.
Příklad
Kat timpf
V následujícím programu není „a“ implicitně převedeno 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;> }> |
ymail
>
>Výstup
Default Exception>
Výstup:
Default Exception>
Nemovitost 3
Pokud je vyvolána výjimka a nikde není zachycena, program se nenormálně ukončí.
Příklad
V následujícím programu je vyhozen znak, ale neexistuje žádný blok pro zachycení 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ýstup
terminate called after throwing an instance of 'char'>
Toto abnormální ukončovací chování můžeme změnit napsáním naší neočekávané funkce.
Poznámka : Odvozená výjimka třídy by měla být zachycena před výjimkou základní třídy.
Stejně jako Java má knihovna C++ a standardní výjimka class, která je základní třídou pro všechny standardní výjimky. Všechny objekty vržené komponentami standardní knihovny jsou odvozeny z této třídy. Chytáním tohoto typu lze tedy zachytit všechny standardní výjimky.
Nemovitost 4
Na rozdíl od Javy jsou v C++ všechny výjimky nekontrolované, tj. kompilátor nekontroluje, zda je výjimka zachycena nebo ne (viz tento pro detaily). Není tedy nutné uvádět všechny nezachycené výjimky v deklaraci funkce. Zpracování výjimek je však doporučeným postupem.
Příklad
Následující program se zkompiluje dobře, ale v ideálním případě by signatura fun() měla uvádět nekontrolované výjimky.
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ýstup
java převod celého čísla na řetězec
Caught exception from fun()>
Lepší způsob, jak napsat výše 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;> }> |
>
>Výstup
Caught exception from fun()>
Poznámka : Použití specifikace Dynamic Exception Specification bylo od C++11 zastaralé. Jedním z důvodů může být to, že může náhodně přerušit váš program. To se může stát, když vyvoláte výjimku jiného typu, který není uveden ve specifikaci dynamické výjimky. Váš program se sám přeruší, protože v tomto scénáři volá (nepřímo) termin(), který standardně volá abort().
Nemovitost 5
V C++ lze vnořit bloky try/catch. Výjimku lze také znovu vyvolat pomocí throw; .
Příklad
Následující program ukazuje vnoření bloků try/catch.
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ýstup
Handle Partially Handle remaining>
Funkce může také znovu hodit funkci pomocí stejného hodu; syntax. Funkce může zpracovat část a požádat volajícího, aby zpracoval zbývající část.
Nemovitost 6
Když je vyvolána výjimka, všechny objekty vytvořené uvnitř uzavřeného bloku try jsou zničeny před přenesením ovládacího prvku do bloku catch.
Příklad
Následující program demonstruje výše uvedenou vlastnost.
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;> >}> }> |
>
>Výstup
Constructor of Test Destructor of Test Caught 10>
Omezení zpracování výjimek v C++
Zpracování výjimek v C++ má také několik omezení:
- Výjimky mohou narušit strukturu nebo tok kódu, protože v kódu je vytvořeno více neviditelných výstupních bodů, což ztěžuje čtení a ladění kódu.
- Pokud není zpracování výjimek provedeno správně, může také vést k úniku prostředků.
- Je těžké se naučit, jak psát kód výjimky, který je bezpečný.
- Neexistuje žádný standard C++, jak používat zpracování výjimek, a proto existuje mnoho variant v postupech zpracování výjimek.
Závěr
Zpracování výjimek v C++ se používá k řešení neočekávaných událostí pomocí bloků try and catch k efektivnímu řešení problému. Toto zpracování výjimek činí naše programy spolehlivějšími, protože chyby za běhu lze zpracovávat samostatně a také pomáhá předcházet zhroucení programu a náhlému ukončení programu, když dojde k chybě.
jak spustit skript v linuxu
Související články:
- Nahoru Otázky a odpovědi v rozhovoru pro zpracování výjimek C++
- Kvíz o zpracování výjimek v C++