PB161 programování v C++ Výjimky Bezpečné programování
Chyby... Snaha psát programy bez chyb myslet : ) Snaha psát programy se schopností fault tolerance. snaha se z chybového stavu dostat lze řešit testováním všeho možného nebo v C++ využitím výjimek pokusné bloky handlery inteligentní probublávání výjimek...
Výjimky dle C++ C++ podporuje pouze práci se synchronními výjimkami lze chytit stav dělení s nulou vyvolány částí programu nelze chytit stav zmáčknuto CTRL+C Výjimky v C++ jsou organizovány do třídní hierarchie dle dědičnosti. při zachytávání výjimek se bere tato hierarchie v potaz lze vytvářet vlastní výjimky
Pokusný blok try { př íkazy } seznam_handlerů Část programu uzavřené do složených závorek uvozených klíčovým slovem try. Nedojde li k výjimce příkazy bloku se dokončí handlery se přeskočí řízení pokračuje za seznamem handlerů
Pokusný blok (2) try { př íkazy } seznam_handlerů Dojde li v tomto bloku k výjimce zbytek neprovedených příkazů bloku se přeskočí hledá se handler, který ošetří vzniklou výjimku (tzv. výjimku zachytí) nalezne li se, provede se případná série příkazů u něj uvedených řízení pak pokračuje za handlerem nenalezne li se, probublá výjimka do nadřazeného bloku dostane li se výjimka až do nejvyššího bloku a není li ošetřena ani tam, dojde k ukončení programu ( neošetřená výjimka, zavolá se terminate())
Handler catch (deklarace_výjimky) { př íkazy } Seznam handlerů je pak posloupnost jednotlivých handlerů zapsaných přímo za sebou. deklarace_výjimky podobná syntaktická pravidla jako deklarace formálních parametrů funkcí nebudeme li potřebovat uvnitř handleru hodnotu výjimky, netřeba uvádet identifikátor vývolané výjimky výpůstka ( ) značí, že handler ošetří všechny vzniklé výjimky v bloku uvádí se většinou jako poslední handler v seznamu
Handler catch (deklarace_výjimky) { př íkazy } Handler má vždy jen max. jeden parametr bez implicitní hodnoty. Výjimka se považuje za ošetřenou, vstoupí li řízení do handleru. Zavoláme li v handleru throw;, dojde k předání téže výjimky do nadřezeného bloku. částečné ošetření výjimky pozor, v nadřazeném bloku musí být výjimka ošetřena
Výběr handleru Dle typu výjimky uvedenou u handleru. Uplatňují se základní pravidla OOP Pravidla: potomek může vždy zastoupit předka typ vzniklé výjimky se musí úplně shodovat s typem výjimky uvedeným u handleru, kromě: T, const T, T&, const T& u handleru akceptují jednoznačného a dostupného potomka T T* akceptuje výjimku typu U*, lze li T* přetypovat na U* pomocí standardních konverzních ukazatelů
Úkol Doplňte do programu deleni.cc výjimky tak, aby nedošlo k pádu programu, ale k výpisu chybového hlášení. Nepoužívejte ošetření dle C (prostý výpis). Použijte try{}, catch() {}, throw
Pozitivní vlastnost šíření výjimky Při šíření výjimky dochází v probublávaných blocích k volání destruktorů objektových typů s paměťovou třídou auto. Jelikož v C++ nemohou být dvě a více výjimek na stejné úrovni, nesmí dojít k vyvolání jiné výjimky v průběhu hledání vhodného handleru pro ošetření stávající výjimky. destruktory pokud možno psát tak, aby se z nich nemohla výjimka rozšířit nikdy uncaught_exception()
Výjimka v konstruktoru Z konstruktoru se pricipielně rozšířit výjimka může, ale jedná li se o globální objekt, nikdo výjimku nezachytí program končí je li volán konstruktor, ze kterého se rozšíří výjimka, v inicializační části konstruktoru jiné třídy volání (a vznik výjimky) proběhne před vstupem do těla volajícího konstruktoru nemůže tedy výjimku ošetřit program končí (resp. nemusí, ale ošetření nebude... adekvátní)
Výjimky a funkce Rozšíříme význam slova PROTOTYP funkce. typ název (parametry) throw(seznam typ ů); seznam_typů typy výjimek, které se smí z funkce rozšířit při snaze o propagaci jiné výjimy, dojde k chybě volání funkce unexpected() a časem terminate() Je li seznam prázdný, nesmí se z funkce rozšířit žádná výjimka. Není li specifikace throw... uvedena vůbec, smí se z funkce rozšířit libovolná výjimka.
Částečné ošetření výjimky V handleru, který vzniklou výjimku zachytí, zavoláme příkaz: throw; Výjimka je poslána do nadřazeného bloku, jakoby nebyla ošetřena vůbec. Musí ji nějaký handler na její cestě vzhůru něco (handler ; )) zachytit.
Výjimka v handleru try { // 1. try blok try { // 2. try blok } catch (){ // handler pro 2. try } } catch (){ // pro 1. try }
Vlastní výjimky Můžeme specifikovat vlatní typy výjimek lze dědit od standardních. Při přetížení metody what() je nutno dodržet prototyp: const char* what(void) const throw(); Stále platí pravidlo OOP, že potomek může zastoupit předka vytvoříme li vlastní hierarchii výjimek, které budou potomky nějaké výjimky, budou fungovat programi, které nebyly přímo napsány pro naši hierarchii
Úkol error_vector error_vector povinný úkol