Sunteți pe pagina 1din 6

Tratarea excepiilor.

1. Tratarea erorilor n C. 2. Tratarea excepiilor n C++. 3. Zone de nume. 1. Tratarea erorilor n C. n C exist dou moduri de tratare a erorilor la execuie: cu reluare la apariia erorii se execut o secven de instruciuni, avnd ca scop eliminarea erorii, dup care se continu programul tratarea erorilor fatale constnd n suspendarea execuiei programului, cu ntoarcerea unui cod de eroare la procesul printe.

Funciile void exit(int) i void abort(void), declarate n <stdlib.h> suspend execuia programului din care sunt lansate. Apelul funciei exit() : elibereaz zonele tampon alocate, nchide fiierele deschise, apeleaz destructorii obiectelor statice utilizate, suspend aplicaia, transmind parametrul din apel procesului printe, interpretat de acesta ca un cod de eroare dac are valoare nenul (EXIT_FAILURE); o valoare nul reprezint o terminare normal a aplicaiei (EXIT_SUCCES). Un efect identic se obine prin execuia instruciunii return cod_er; lansat din funcia int main(). naintea eliberrii resurselor i suspendrii execuiei programului prin exit() este posibil s executm mai multe funcii, care au fost nregistrate prin apeluri ale funciei atexit(). Aceasta are ca parametru un pointer la funcia nregistrat. Exemplu: #include <stdlib> void f(){. . .}; void g(){. . .}; void main(){ atexit(g); //inregistrarea functiilor care se executa atexit(f); //in ordinea f(), g() la terminare normala //sau anormala a programului . . . exit(1); //se executa f(), g() inainte de suspendare . . . //si aici se executa f(), g() la terminare normala } Apelul funciei abort() ntrerupe imediat aplicaia, fr eliberarea resurselor i apelarea destructorilor obiectelor statice, cu returnarea codului de eroare 3 i afiarea mesajului abnormal program termination. Utilizarea macroinstruciunii assert(condiie) , definit n <assert.h> permite testarea validitii unor condiii. Valoarea 0 a condiiei suspend execuia programului i afieaz mesajul: Assertion failed (conditie) __FILE__ ff __LINE__ ll. Aceast macroinstruciune este folosit mai ales n faza de depanare a programelor.

Pentru a elimina secvenele assert() dup depanarea programului, se definete macroinstruciunea assert() n mod condiionat de prezena unei constante simbolice NDEBUG. #define NDEBUG #include <assert.h> . . . 2. Tratarea excepiilor n C++. O excepie reprezint o condiie de eroare, care transmis sistemului determin producerea unei erori la execuie. De exemplu: o nprire prin 0, ieirea indicelui n afara limitelor unui tablou, etc. La apariia unei excepii, utilizatorul i poate defini o secven proprie de tratare a acesteia. n C++ se utilizeaz un model ierarhic de tratare a excepiilor. Acesta folosete 3 cuvinte cheie: try detectare, catch tratare, throw activare. Transmiterea informaiilor se va face prin intermediul unor obiecte excepii. Cuvntul try delimiteaz un bloc din programul utilizatorului, care va fi supravegheat pentru a detecta apariia unor excepii. n cazul apariiei unui anumit tip de excepie, este pasat excepia sesizat prin throw(obiect_exceptie) rutinei de tatare corespunztoare, care ncepe prin catch(obiect_exceptie). Excepia poate fi captat, specificnd numai tipul ei, prin catch(tip_exceptie). La apariia excepiei este construit un obiect avnd tipul excepiei corespunztoare i se activeaz excepia. Membrii obiectului servesc la identificarea naturii excepiei. Rutina de tratare a excepiei urmeaz imediat dup blocul try: catch(tip_exceptie){ // rutina de tratare a exceptiei; } S considerm dou excepii, care pot s apar n cazul folosirii vectorilor: ieirea indicilor n afara limitelor vectorului - clasa excepie Range construirea unui vector cu dimensiune care depete dimensiunea maxim admis clasa excepie Size

Primul tip de excepie apare la indexare, deci excepia va fi activat n funcia operator de indexare. A doua excepie apare la declararea unui obiect vector, deci excepia va fi activat n constructorul clasei vector. Clasele excepii vor fi declarate drept clase incluse n clasa Vector: class Vector{ float* v; int d; enum{DMAX=100}; public: class Range{};

// numar de elemente vector // dimensiune maxima vector // clase exceptii

class Size {}; Vector(int n); // constructor float& operator[](int i);//functie operator de indexare }; Vector::Vector(int n){ if(n < 0 || n >= DMAX) throw Size(); d = n; v = new float[n]; }; float& Vector::operator[](int I){ if(i >= 0 && i < d) return v[i]; throw Range(); return v[0]; }; void main(){ try{ Vector x[200]; // declanseaza exceptia Size int i=150; x[i] = 1.5; // declanseaza exceptia Range . . . }; catch(Vector::Size){ . . . // rutina de tratare exceptie Size . . . }; catch(Vector::Range){ . . . // rutina de tratare exceptie Range . . . }; } 3. Zone de nume. n programele mari, scrise de mai muli programarori, partajate n mai multe fiiere surs, riscul conflictelor de nume (de variabile, funcii, clase, obiecte) este ridicat. O regiune declarativ a unui program este o zon n care se fac declaraii. Astfel regiunea declarativ a unei variabile locale o reprezint funcia, iar a unei variabile globale este fiierul n care este declarat. Domeniul potenial de vizibilitate al unui nume se ntinde de la declararea acestuia pn la sfritul regiunii declarative. O variabil poate s nu fie vzut peste tot n domeniul potenial de vizibilitate. Ea poate fi ascuns de ctre un alt variabil cu acelai nume, declarat ntr-o regiune declarativ imbricat. Domeniul de vizibilitate reprezint zona n care variabila poate fi accesat. 3

O zon de nume este un mecanism de exprimare a unei grupri logice. Declararea zonei de nume se face printrr-o interfa de forma: namespace nume{ declaraii entiti (variabile, funcii, etc) }; De exemplu, o zon de nume FunMatGrade, n care se declar funcii trigonometrice cu argumentul exprimat n grade, care pstreaz aceleai nume cu cele din fiierul antet <math.h> este: namespace FunMatGrade { double sin(double); double cos(double); . . . }; Definirea zonei de nume, este de obicei separat de declarare, fiind situat n partea de implementare. n definiie, numele definite sunt calificate cu numele zonei, folosind operatorul de rezoluie. Astfel numele din zona de nume dat mai sus se definesc prin: double FunMatGrade :: sin(double){/* . . . */}; double FunMatGrade :: cos(double){/* . . . */}; . . . Accesul la un nume din zona de nume se face de asemeni calificat. Exemplu: y = FunMatGrade :: sin(x); Aceste notaii lungi i greoaie pot fi evitate folosind declaraii de utilizare. Acestea sunt formate din using i numele calificat, care n continuare poate fi folosit necalificat. Astfel: using FunMatGrade :: sin(double); ne permite s apelm funcia definit pentru calculul sinusului prin y=sin(x). Pentru a putea folosi funcia obinuit de calcul a sinusului, declarat n <math.h> , vom preceda numele cu operatorul de rezoluie, adic y= :: sin(x). Aceasta reprezint zona de nume global i corespunde regiunii declarative la nivel de fiier. Zonele de nume sunt deschise, adic putem aduga nume la zone existente. Declaraia de utilizare adaug un nume la regiunea declarativ local, mpiedicnd declararea altei variabile locale cu acelai nume (i ascunznd variabila global cu acelai nume). Exemplu: namespace A{ int x; void f(); };

char x; //nume global void main(){ using A::x; //x din zona de nume considerat local double x; //eroare, exista x local din zona de nume cin >> ::x; //citeste x global } Directiva de utilizare using namespace A; aplic declaraia de utilizare tuturor numelor din zona de nume, care devin locale n zona curent. De exemplu: #include <iostream> using namespace std; face ca toate numele din zona de nume std s devin globale. Dac un nume este declarat local unei funcii, el nu poate fi importat cu o declaraie de utilizare. Numele poate fi importat cu o directiv de utilizare, dar va fi ascuns de ctre numele local. Astfel: char x; //declarat global void main(){ double x; //declarat local; using namespace A; //se accepta,dar using A::x //este ilegal cin >> x; //x local, celelalte sunt ascunse cin >> ::x; //x global cin >> A::x; //x din zona de nume } Dac nu folosim directiva de utilizare, vom adopta una din variantele: #include <iostream> . . . int x; std::cin >> x; std::cout << x << std::endl; respectiv: #include <iostream> . . . using std::cin; using std::cout; using std::endl; int x; cin >> x; cout << x << endl; O zon de nume poate fi inclus n alt zon de nume. n acest caz accesul la numele declarate n zona interioar se face prin dubl calificare: namespace A{ namespace B{ double b; }; int a; 5

} Calificarea A::B::b poate fi evitat cu declaraia de utilizare using A::B. Pentru a crea un sinonim B al unei zone de date A scriem namespace B=A; Directiva de utilizare este tranzitiv: namespace A{ int x; } namespace B{ using A::x; . . . } ne permite s accesm pe x prin A::x sau B::x. Toate clasele, obiectele i funciile din biblioteca standard C++ se definesc n zona de nume std. Fiierele antet au aceleai nume cu fiierele antet corespunztoare anterioare, dar le lipsete extensia .h.

S-ar putea să vă placă și