Výjimky v C++

C++ Objektově orientované programování Výjimky v C++

Výjimky jsou určeny k přechodu z místa, kde vznikla chyba do místa, kde je možné chybu ošetřit, nebo alespoň zabránit ztrátě dat. Slovo výjimka má dva významy, může to být označení samotné chyby, nebo to může být objekt, který o chybě nese zprávu.

hierarchie

exception - společný předek všech tříd
bad_alloc - vyvolá ji operátor new, pokud se mu nepodaří alokovat potřebnou paměť
bad_cast - chyba v přetypování u operátoru dynamic_cast<>()
ios_base::failure - chyba vstupu či výstupu
bad_typeid - operátor typeid() ji vyvolá, pokud mu předáme ukazatel s hodnotou 0
bad_exception - na tento typ se dají přetransformovat neočekávané výjimky
logic_error - vyhrazeno pro chyby, na které bylo možné přijít předem

  • length_error - chybná délka (např třída vektor při prodloužení pole nad max_size)
  • domain_error - chyba definičního oboru
  • out_of_range - překročení rozsahu
  • invalid_argument - neplatný argument (parametr)

runtime_error - vyhrazeno pro chyby, na které nebylo možné přijít předem

  • overflow_error - přetečení
  • underflow_error - podtečení
  • range_error - chyba rozsahu

Jako výjimky můžeme použít instance tříd deklarovaných v standardním hlavičkovém souboru <exception>(jejichž dědická hierarchie je k vidění na obrázku), základní datové typy (int, double), nebo své vlastní třídy. Taková třída by mohla vypadat například takto:

class vyjimka
{
        char* text;
public:
        char* get_error_message(void)
        {
        return text;
        }
        vyjimka();
        vyjimka(char*);
};
vyjimka::vyjimka()
{
        text="...";
}
vyjimka::vyjimka(char*txt)
{
        text=txt;
}

Výjimka se v programu vyvolává příkazem throw, za který se napíše hodnota (v případě základních datových typů to bude číslo nebo znak. V případě objektových typů daný typ a závorky s parametry předávanými konstruktoru).

throw 5;
throw overflow_error(“příliš velká hodnota“);

Výjimky se dají zachytit blokem try-catch, za který musíme napsat závorky s typem výjimky, kterou chceme zachytit. Kromě pravidla, že potomek může vždy zastoupit předka, se neprovádějí žádné převody mezi typy. Chceme-li zachytit všechny typy výjimek, napíšeme do závorek 3 tečky:

try
{
//příkazy, které mohou vyvolat výjimku
}
catch(typ výjimky)
{
//ošetření výjimky
}

nebo

try
{
//příkazy, které mohou vyvolat výjimku
}
catch(…)
{
//ošetření výjimky
}

Můžeme zachytit samozřejmě i několik druhů výjimek v jednom try-catch bloku. Příkazů catch prostě napíšeme několik. Jako poslední se uvádějí nejobecnější typy výjimek. Jazyk C++ navíc umožňuje tímto blokem nahradit celé tělo funkce (i se složenými závorkami). Za hlavičku funkce navíc smíme připsat throw(Výjimky, které ve funkci smí vzniknout). Takže kód může vypadat i takto:

int faktorial(int cislo) throw(domain_error)
try
{
if((cislo>12)||(cislo<0))throw domain_error("chybná hodnota");
//...
}
catch(logic_error)
{
//...
}

Neočekávaná výjimka

Pokud za hlavičkou funkce uvedeme typy povolených výjimek a ve funkci vznikne výjimka jiného typu, nastane neočekávaná výjimka. Pokud neurčíme jiné chování, způsobí neočekávaná výjimka okamžité ukončení programu (nebo pokud není za hlavičkou funkce uveden typ bad_exception na který by se výjimka může převést).

Šíření výjimky

Pokud v programu vznikne výjimka mimo blok try-catch nebo pokud k danému bloku není připojena obsluha tohoto typu výjimky vystoupí výjimka z bloku, ve kterém se právě nachází (z funkce, ve které vznikla), a pokračuje za tímto blokem (za příkazem volání funkce). Tento proces se nazývá šíření výjimky.

Neošetřená výjimka

Pokud výjimka dojde na konec programu, aniž by nalezla správnou obsluhu, vznikne neošetřená výjimka. Ta volá funkci terminate(),která pokud není nastaveno jiné chování, ukončí program. Chování funkce terminate() lze změnit voláním funkce set_terminate(), které předáme funkci, jež má zavolat. Pokud tato funkce program neukončí, zavolá terminate() po návratu z ní funkci abort().

Pokud není možné zachycenou výjimku na daném místě ošetřit, ale je nutné udělat něco jiného (například zabránit ztrátě dat), je možné po „záchranných akcích“ poslat výjimku dál prázdným příkazem throw:

catch(exception &ex)
{
//...
throw;
}

A to by bylo pro dnešek vše. :-)


 

  Aktivity (1)

Článek pro vás napsal Zdeněk Pavlátka
Avatar
Autor se věnuje spoustě zajímavých věcí :)

Jak se ti líbí článek?
Celkem (4 hlasů) :
3.753.753.753.75 3.75


 


Miniatura
Předchozí článek
Dědičnost a polymorfismus
Miniatura
Následující článek
Šablony v C++

 

 

Komentáře

Avatar
nf fn
Člen
Avatar
nf fn:

throw(výjimky, které smí ve funkci vzniknout) je podle mě od C++11 označeno jako zastaralé

 
Odpovědět 24. července 13:12
Avatar
Zdeněk Pavlátka
Tým ITnetwork
Avatar
Odpovídá na nf fn
Zdeněk Pavlátka:

Ten článek jsem psal před vznikem C++11. A ano je.

Odpovědět  +2 24. července 22:41
Kolik jazyků umíš, tolikrát jsi programátor.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 2 zpráv z 2.