10. bˇrezna 2015, Brno ´ Pˇripravil: David Prochazka
´ Prace s vyjimkami ´ Programovac´ı jazyk C++
ˇ K cemu slouˇz´ı vyjimky ´
ˇ Obsah pˇredna´ sky 1
K cˇ emu slouˇz´ı v´yjimky
2
´ ren´ı v´yjimek Vytvaˇ
3
´ ı pˇr´ıpady Specialn´
4
Hierarchie v´yjimek
5
Standardn´ı v´yjimky
6
Shrnut´ı
Strana 2 / 25
ˇ K cemu slouˇz´ı vyjimky ´
Strana 3 / 25
Jak se muˇ ˚ ze program zachovat pˇri chybeˇ Dˇr´ıve byl obvykl´y zpusob zavolat metodu abort. ˚ Metoda okamˇziteˇ ´ ´ ˇ vyprazdnila vyrovnavac´ ı pamet, ukonˇcila cel´y program, ´ ´ vratila cˇ ´ıslo nadˇrazeneho procesu, ´ sku o ukonˇcen´ı. vypsala na chybov´y v´ystup hlaˇ
Alternativneˇ se vyuˇz´ıvala metoda exit. ´ Nejednalo se o elegantn´ı ˇreˇsen´ı, proto byl preferovan ´ mechanismus navratov´ ych hodnot. Metoda v tomto pˇr´ıpadeˇ neukonˇcuje program, jen signalizuje chybu. ´ Navratovou hodnotu je vˇsak moˇzne´ ignorovat. ´ ˇ s´ı Navratov a´ hodnota nenese obvykle komplexnejˇ ˇ informace o chybe.
ˇ K cemu slouˇz´ı vyjimky ´
Strana 4 / 25
Vyjimky ´ Vyj´ımka pˇredstavuje zaj´ımav´y zpusob, jak signalizovat ˚ programu, zˇ e v urˇcite´ entiteˇ nastala chyba. ˇ s´ı problemy ´ ˇ e´ u navratov´ ´ Reˇ zm´ınen ych hodnot. V´yjimky pouˇz´ıva´ ˇrada funkc´ı/metod ˇ (pˇr´ıstup pomoc´ı metody at() na m´ısto v ˇretezci). ´ Je vyvolana pomoc´ı pˇr´ıkazu throw. Hodnotou, ktera´ je jako vyj´ımka vyhozena muˇ ˚ ze b´yt ´ jednoduch´y datov´y typ, obvykle pouˇz´ıvame objekty. V´yjimky si muˇ ˚ zeme nadefinovat sami, pouˇz´ıt standardn´ı v´yjimky a v´yjimky od nich odvozene´ (doporuˇceno). ´ ana ´ ´ ´ jako try. V´yjimka je odchytav v bloku kodu oznaˇcenem ˇ Reˇsena je v bloku catch(). Uˇzit´ı v´yjimek v´yrazneˇ zpomaluje program.
ˇ K cemu slouˇz´ı vyjimky ´
Strana 5 / 25
Implementace 1 2 3 4 5
try { // pokus o operaci potencialne vyhazujici vyj . } catch ( myException & e ) { // osetreni neplatneho pokusu }
V bloku catch je uveden odkaz na v´yjimku. Ve skuteˇcnosti se vˇsak jedna´ o odkaz na kopii. Puvodn´ ı v´yjimka obvykle v dobeˇ ˚ ´ ı jiˇz neexistuje. zpracovan´
ˇ K cemu slouˇz´ı vyjimky ´
Strana 6 / 25
ˇ ren´ı vyjimky Pˇr´ıklad osetˇ ´ u metody at() ´ ı v´yjimky, beh ˇ programu se Dojde-li v bloku try k vyvolan´ pˇreruˇs´ı a pˇrejde se k nejbliˇzsˇ ´ımu handleru v´yjimek – catch. 1 2
# include < exception > # include < string >
3 4 5 6 7 8 9 10 11 12 13
int main () { std :: string s ( " 1234 " ); try { s . at (5); std :: cout << " toto se nikdy nevypise " ; } catch ( exception & e ) { std :: cerr << " Nastala chyba " << std :: endl ; std :: cerr << e . what () << std :: endl ; } ...
´ ren´ı vyjimek Vytvaˇ ´
ˇ Obsah pˇredna´ sky 1
K cˇ emu slouˇz´ı v´yjimky
2
´ ren´ı v´yjimek Vytvaˇ
3
´ ı pˇr´ıpady Specialn´
4
Hierarchie v´yjimek
5
Standardn´ı v´yjimky
6
Shrnut´ı
Strana 7 / 25
´ ren´ı vyjimek Vytvaˇ ´
Strana 8 / 25
Pˇr´ıklad Zlomek Vytvoˇrte tˇr´ıdu reprezentuj´ıc´ı zlomek, kter´y obsahuje atributy ´ ma´ metodu vydel, ˇ ktera´ vyhazuje citatel a jmenovatel. Dale ˇ ı nulou. V´yjimku reprezentujte vlastn´ı v´yjimku v pˇr´ıpadeˇ delen´ ´ tˇr´ıdou obsahuj´ıc´ı popis problemu (lze rozˇs´ıˇrit o dalˇs´ı informace – hodnoty cˇ itatele a jmenovatele, atp.). 1 2 3 4 5 6 7
class MatChyba { private : std :: string m_popis ; public : void MatChyba ( std :: string d ) { m_popis = d ; } std :: string getPopis () { return m_popis ; } };
´ ren´ı vyjimek Vytvaˇ ´
Strana 9 / 25
ˇ ı vyhozen´ı vyjimek Rucn´ ´ ˇ Pokud ma´ m´ıt nekter a´ funkce moˇznost vyvolat v´yjimku, mus´ı to b´yt uvedeno v deklaraci funkce (metody). Pokud muˇ ˚ ze funkce ´ vracet v´yce typu˚ v´yjimek, mus´ı b´yt v zavorce vˇsechny. 1 2 3 4 5 6 7 8 9 10
class Zlomek { private : int m_citatel , m_jmenovatel ; public : Zlomek ( int citatel , jmenovatel ){ m_citatel = citatel ; m_jmenovatel = jmenovatel ; } double vydel () throw ( MatChyba ); };
´ ren´ı vyjimek Vytvaˇ ´
Strana 10 / 25
Implementace metody vydel() 1 2 3 4 5 6 7 8 9
double Zlomek :: vydel () throw ( MatChyba ){ if ( m_jmenovatel == 0) { MatChyba v ( " Deleni nulou ve zlomku " ); throw v ; // lze vyhodit i nepojmenovanou instanci tridy // throw MatChyba (" Popis problemu "); } return (( double ) m_citatel / m_jmenovatel ); }
´ Je durazn eˇ doporuˇcovano vyhazovat v´yjimky hodnotou a ˚ ´ odchytavat odkazem.
´ ren´ı vyjimek Vytvaˇ ´
Strana 11 / 25
Jak vyjimku ´ zpracujeme? 1
Zlomek * z = new Zlomek (10 ,0);
2 3 4 5 6 7 8 9 10 11 12 13
try { std :: cout << " 10/0= " << z - > vydel () << std :: endl ; std :: cout << " Pokud je delitel != 0 vypise se to " ; } catch ( MatChyba & v ) { // pokud je vyhozena Vyjimka std :: cout << v . vrat () << std :: endl ; } catch ( LogChyba & j ) { // pokud jina ... // opetovne uvolneni vyjimky pro zpracovani // specialni pripad , bezne nedelame ! throw ; }
´ ren´ı vyjimek Vytvaˇ ´
ˇ Odchycen´ı vsech vyjimek ´ ´ V zavorce jsou opravdu tˇri teˇcky. 1 2 3 4 5
try { // vyvolani vyjimky } catch (...) { // osetreni }
´ Nelze vˇsak identifikovat typ v´yjimky – druh problemu.
Strana 12 / 25
´ ı pˇr´ıpady Specialn´
ˇ Obsah pˇredna´ sky 1
K cˇ emu slouˇz´ı v´yjimky
2
´ ren´ı v´yjimek Vytvaˇ
3
´ ı pˇr´ıpady Specialn´
4
Hierarchie v´yjimek
5
Standardn´ı v´yjimky
6
Shrnut´ı
Strana 13 / 25
´ ı pˇr´ıpady Specialn´
Strana 14 / 25
ˇ ren´ı zrusen´ ˇ ı objektu – specialn´ ´ ı pˇr´ıpad! Osetˇ 1 2
// nekde v metode Trida * instance = new Trida ;
3 4 5 6 7
... // kod , ktery potencialne vyhodi vyjimku // tato vyjimka je vyslana mimo metodu ...
8 9 10
delete instance ; ...
Pokud bude vyhozena v´yjimka, objekt se nikdy nezruˇs´ı.
´ ı pˇr´ıpady Specialn´
Strana 15 / 25
ˇ ren´ı zrusen´ ˇ ı objektu – rˇesen´ ˇ ı Osetˇ 1
Trida * instance = new Trida ;
2 3 4 5
try { // kod , ktery potencialne vyhazuje vyjimku } catch ( exception & e ) {
6
delete instance ; // " pozastavenou " vyjimku je treba zase uvolnit throw ;
7 8 9 10
}
a) Nelze to oˇsetˇrit podm´ınkou? b) Metoda nesm´ı v´yjimku odchytit a zruˇsit bez toho, zˇ e by ´ vyˇreˇsila. Pokud problem ´ kter´y vyhozen´ı zpusobil problem ˚ ´ a, ´ mus´ı b´yt v´yjimka (znovu) vypuˇstena. ˇ setrvav
Hierarchie vyjimek ´
ˇ Obsah pˇredna´ sky 1
K cˇ emu slouˇz´ı v´yjimky
2
´ ren´ı v´yjimek Vytvaˇ
3
´ ı pˇr´ıpady Specialn´
4
Hierarchie v´yjimek
5
Standardn´ı v´yjimky
6
Shrnut´ı
Strana 16 / 25
Hierarchie vyjimek ´
Strana 17 / 25
´ ren´ı vyjimek ˇ cnost ˇ Vytvaˇ ´ a dedi 1 2 3 4 5 6 7
class MatChyba { private : std :: string m_popis ; public : MatChyba ( std :: string popis ){ m_popis = popis ;} std :: string getPopis () { return m_popis ; } };
8 9 10 11 12 13 14 15 16 17
class DeleniNulou : public MatChyba { private : int m_delenec ; public : DeleniNulou ( std :: string t , int d ): Vyjimka ( t ){ m_delenec = d ; } int getDelenec () { return m_cislo ; } };
Hierarchie vyjimek ´
Strana 18 / 25
ˇ sen´ ˇ ı jejich odchycen´ı jiˇz bylo zm´ıneno ˇ Re 1
try {
2
// vyvolani v . } catch ( DeleniNulou & v ) { // osetreni } catch ( MatChyba & v ) { // osetreni }
3 4 5 6 7
´ ´ v´yjimky Je nutne´ davat si pozor na poˇrad´ı v jakem ´ ame ´ odchytav (potomek muˇ ˚ ze vystupovat v roli pˇredka!). ´ ate ´ pˇredka, odchyt´ı se i potomek! Pokud nejdˇr´ıve odchytav
Standardn´ı vyjimky ´
ˇ Obsah pˇredna´ sky 1
K cˇ emu slouˇz´ı v´yjimky
2
´ ren´ı v´yjimek Vytvaˇ
3
´ ı pˇr´ıpady Specialn´
4
Hierarchie v´yjimek
5
Standardn´ı v´yjimky
6
Shrnut´ı
Strana 19 / 25
Standardn´ı vyjimky ´
Strana 20 / 25
Standardn´ı vyjimky ´ Sp´ısˇ e, neˇz definovat si vlastn´ı v´yjimky, je vhodne´ vyuˇz´ıvat ´ standardn´ıch v´yjimek, pˇr´ıpadneˇ odvozene. V´yjimky jsou odvozeny od tˇr´ıdy exception. ´ ı metodu what(). Tato tˇr´ıda obsahuje virtualn´ Z n´ı jsou odvozene´ logic error (chyby v logice programu) ˇ a runtime error (chyby zjistitelne´ aˇz za behu programu). Abychom mohli pouˇz´ıvat standardn´ı v´yjimky, je nutne´ naˇc´ıst stdexcept. ´ a´ ze standardn´ıch Pokud uˇzivateli nevyhovuje zˇ adn ´ hierarchie. v´yjimek, je vhodne´ odvodit vlastn´ı z teto ´ aby se programator ´ Proto je vhodne, nejdˇr´ıve dobˇre ´ seznamil se standardn´ımi v´yjimkami.
Standardn´ı vyjimky ´
Strana 21 / 25
Standardn´ı vyjimky ´ Z logic error se odvozuj´ı: ´ ana ´ domain error – asinu je pˇredav hodnota mimo interval -1, 1, ´ ´ invalid argument – funkci byla pˇredana neoˇcekavan a´ hodnota, length error – pro poˇzadovanou operaci nen´ı dostatek m´ısta (append), out of bounds – obvykle sˇ patn´y index.
Z runtime error se odvozuj´ı: ´ underflow error – pokud pˇri v´ypoˇctech v plovouc´ı cˇ arce ´ ı zobrazitelne, ´ vyjde cˇ ´ıslo, ktere´ je menˇs´ı, neˇz minimaln´ ˇ s´ı, neˇz maximaln´ ´ ı overflow error – v´ysledek cˇ ´ıslo je vetˇ ´ zobrazitelne, range error – v´ysledek je mimo obor hodnot.
A znich zase dalˇs´ı...
Standardn´ı vyjimky ´
Strana 22 / 25
Pˇr´ıklad standardn´ı vyjimky ´ 1 2 3 4 5 6
Trida * objekt ; try { objekt = new Trida ; } catch ( std :: bad_alloc & b ) { std :: cout << " Vyhodil vyjimku " << std :: endl ; }
´ ı v´yjimky lze zamezit a provest ´ ruˇcn´ı oˇsetˇren´ı. Je ale Vyvolan´ ´ ı chyby. Nicmen ´ eˇ v nekter´ ˇ nutne´ peˇcliveˇ hl´ıdat potencialn´ ych situac´ıch, kdy je potˇreba optimalizovat na v´ykon se to muˇ ˚ ze hodit (nothrow).
Standardn´ı vyjimky ´
Strana 23 / 25
Pˇr´ıklad na odvozen´ı vyjimky ´ Zlomek Zkuste se zamyslet nad pˇr´ıkladem se zlomkem a upravit jej tak, ˇ aby podporoval nekterou z hierarchie standardn´ıch v´yjimek. ´ se pokuste vytvoˇrit vlastn´ı a zaˇradit ji do hierarchie. Dale
Shrnut´ı
ˇ Obsah pˇredna´ sky 1
K cˇ emu slouˇz´ı v´yjimky
2
´ ren´ı v´yjimek Vytvaˇ
3
´ ı pˇr´ıpady Specialn´
4
Hierarchie v´yjimek
5
Standardn´ı v´yjimky
6
Shrnut´ı
Strana 24 / 25
Shrnut´ı
Strana 25 / 25
Shrnut´ı ˇ Vyjimky ´ jsou doplnek ´ ı navratov´ ´ V´yjimky nenahrazuj´ı zcela pouˇz´ıvan´ ych hodnot ´ ´ funkc´ı/metod jako indikatoru chyboveho stavu. Jedna´ se o ˇ kter´y umoˇznuje ˇ ´ ´ urˇcit´y komplexn´ı doplnek, lepe pˇredavat ´ informace o tom co se vlastneˇ stalo a lepe take´ ˇreˇsit situace, kde muˇ ˚ ze doj´ıt ˇradeˇ ruzn´ ˚ ych chyb (najednou).
´ ´ Pˇredchazejte vyjimk ´ am ´ Je obvykle vhodne´ pˇredchazet vyhozen´ı v´yjimky kontrolou ´ vstupn´ıch hodnot atp. V´yjimka ma´ roli urˇcite´ zahrann e´ brzdy“. ”