Kivételkezelés a C++ nyelvben Bevezetés Ficsor Lajos Miskolci Egyetem Általános Informatikai Tanszék Ficsor Lajos Kivételkezelés a C++ nyelvben
Hagyományos hibakezelés Függvény visszatérési értéke (paramétere) hátrányai: azonosítás hibaérték / valódi érték hívási hierarchia! globális változó C++: hibastátusz adattag és visszaadó függvény Ellenőrzés nehézkes, sok helyre kell beiktatni. Kód áttekinthetőségét rontja! Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Kivétel fogalma Nem azonos az operációs rendszer exeption fogalmával. Kivétel az, amit programozó annak tekint. A C++ szemléletében a kivétel egy objektum, ami a kivétel bekövetkezésekor jön létre. Kivétel kiváltása: throw Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben A kivételek kezelése try blokk: a "védett" programrészt fogja közre. try { utasítások } catch blokk(ok): a keletkezett kivételek lekezelése catch (típus paraméter) {utasítások} vagy catch ( típus ) catch ( ... ) Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Egyszerű példa 1. try { //utasítások char* szoveg = new char[200]; if ( szoveg == 0 ) throw "nincs memória"; //további utasítások } Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Egyszerű példa 2. catch ( char* uzenet ) { cout << uzenet << '\n'; //további utasítások az adott //állapot (most hiba) lekezelésére } Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Működés 1. az első throw utasítással befejeződik a try blokk végrehajtása kilép a blokkból a vezérlés, rendcsinálással verem visszaállítása lokális objektumok megszüntetése létrejön a throw utasításban megjelölt objektum egy példánya Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Működés 2. megkeresi a program azt az első catch blokkot, amely a kivétel objektumra illeszkedik (az illeszkedés fogalmát később pontosítjuk) végrehajtja a blokk utasításait a catch blokk végrehajtása után az utolsó catch blokk utáni első utasításra kerül a vezérlés ha kivétel keletkezett, de egy catch blokk sem illeszkedett, a terminate függvény hívódik meg, ami leállítja a programot Ficsor Lajos Kivételkezelés a C++ nyelvben
Egymásba ágyazott kivételkezelők A try blokkok egymásba ágyazhatók explicit, vagy implicit módon (pl. függvényhívás) A catch blokkok keresése (és a verem visszagombolyítása) "belülről kifelé" történik. Ha verem visszagombolyítás közben újabb kivétel keletkezik, a terminate függvény hívódik meg A kivétel lekezelése (vagy annak egy része) továbbhárítható a feljebb álló szintekre a paraméter nélküli throw utasítással. Ficsor Lajos Kivételkezelés a C++ nyelvben
Leszármaztatott kivétel osztályok Mivel a kivétel egy objektum, kivétel osztályok között lehetséges leszármazási hierarchiát létrehozni, és ezzel csoportosítani a kivételeket. Egy E kivételobjektum illeszkedik a cath (H) blokkra, ha H és E típusa azonos H egy egyértelmű bázisosztálya E-nek H és E pointerek és alaptípusukra a fenti érvényes H egy referencia, és a hivatkozott típusra az első két pont valamelyike érvényes Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Általános catch blokk Formája: catch ( ... ) Erre a blokkra bármilyen kivétel objektum illeszkedik, tehát logikusan csak az utolsó lehet a blokkok sorában. Használhatjuk arra, hogy minden egyéb, speciális kezelés nem igénylő kivételt itt kezeljünk le. Gyakran végződik a kivétel továbbdobásával. Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben class AllocError { int meret; public: AllocError(int m) {meret = m;} void uzenet(void) { cerr << meret << "byte lefoglalasa sikertelen" << "\n"; } }; Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben class Vektor { int n; int* p; public: class RangeError; Vektor(int hatar); int& operator[] (int i); }; Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben class Vektor::RangeError { int index; public: RangeError(void) {index = 0;}; RangeError (int i) {index=i; } void uzenet(void) { cerr<< "Hibas index: " << index << "\n";} }; Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben Vektor::Vektor(int hatar) { n = hatar; p = new int[n]; if (p == 0) throw AllocError(n*sizeof(int)); } Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben int& Vektor::operator[] (int i) { if (i >= 0 && i < n) return p[i]; throw RangeError(i); } Ficsor Lajos Kivételkezelés a C++ nyelvben
Kivételkezelés a C++ nyelvben int main(int argc, char* argv[]) { try { Vektor v(100); v[100] = 5; } catch (AllocError error) { error.uzenet(); } catch (Vektor::RangError r) { r.uzenet(); } return 0; Ficsor Lajos Kivételkezelés a C++ nyelvben