Extras din curs
2. Tratarea exceptiilor în C++.
O exceptie reprezinta o conditie de eroare, care transmisa sistemului determina producerea unei erori la executie. De exemplu: o înpartire prin 0, iesirea indicelui în afara limitelor unui tablou, etc.
La aparitia unei exceptii, utilizatorul îsi poate defini o secventa proprie de tratare a acesteia.
În C++ se utilizeaza un model ierarhic de tratare a exceptiilor. Acesta foloseste 3 cuvinte cheie: try – detectare, catch – tratare, throw – activare.
Transmiterea informatiilor se va face prin intermediul unor obiecte exceptii.
Cuvântul try delimiteaza un bloc din programul utilizatorului, care va fi supravegheat pentru a detecta aparitia unor exceptii. În cazul aparitiei unui anumit tip de exceptie, este pasata exceptia sesizata prin throw(obiect_exceptie) rutinei de tatare corespunzatoare, care începe prin catch(obiect_exceptie).
Exceptia poate fi captata, specificând numai tipul ei, prin catch(tip_exceptie). La aparitia exceptiei este construit un obiect având tipul exceptiei corespunzatoare si se activeaza exceptia. Membrii obiectului servesc la identificarea naturii exceptiei.
Rutina de tratare a exceptiei urmeaza imediat dupa blocul try:
catch(tip_exceptie){
// rutina de tratare a exceptiei;
}
Sa consideram doua exceptii, care pot sa apara în cazul folosirii vectorilor:
• iesirea indicilor în afara limitelor vectorului - clasa exceptie Range
• construirea unui vector cu dimensiune care depaseste dimensiunea maxima admisa – clasa exceptie Size
Primul tip de exceptie apare la indexare, deci exceptia va fi activata în functia operator de indexare.
A doua exceptie apare la declararea unui obiect vector, deci exceptia va fi activata în constructorul clasei vector.
Clasele exceptii vor fi declarate drept clase incluse în clasa Vector:
class Vector{
float* v;
int d; // numar de elemente vector
enum{DMAX=100}; // dimensiune maxima vector
public:
class Range{}; // 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 multi programarori, partajate în mai multe fisiere sursa, riscul conflictelor de nume (de variabile, functii, clase, obiecte) este ridicat.
O regiune declarativa a unui program este o zona în care se fac declaratii. Astfel regiunea declarativa a unei variabile locale o reprezinta functia, iar a unei variabile globale este fisierul în care este declarata.
Domeniul potential de vizibilitate al unui nume se întinde de la declararea acestuia pâna la sfârsitul regiunii declarative.
O variabila poate sa nu fie vazuta peste tot în domeniul potential de vizibilitate. Ea poate fi ascunsa de catre un alta variabila cu acelasi nume, declarata într-o regiune declarativa imbricata.
Domeniul de vizibilitate reprezinta zona în care variabila poate fi accesata.
O zona de nume este un mecanism de exprimare a unei grupari logice.
Declararea zonei de nume se face printrr-o interfata de forma:
namespace nume{
declaratii entitati (variabile, functii, etc)
};
De exemplu, o zona de nume FunMatGrade, în care se declara functii trigonometrice cu argumentul exprimat în grade, care pastreaza aceleasi nume cu cele din fisierul antet <math.h> este:
namespace FunMatGrade {
double sin(double);
double cos(double);
. . .
};
Definirea zonei de nume, este de obicei separata de declarare, fiind situata în partea de implementare.
În definitie, numele definite sunt calificate cu numele zonei, folosind operatorul de rezolutie.
Astfel numele din zona de nume data 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 notatii lungi si greoaie pot fi evitate folosind declaratii de utilizare. Acestea sunt formate din using si numele calificat, care în continuare poate fi folosit necalificat. Astfel:
using FunMatGrade :: sin(double);
ne permite sa apelam functia definita pentru calculul sinusului prin y=sin(x). Pentru a putea folosi functia obisnuita de calcul a sinusului, declarata în <math.h> , vom preceda numele cu operatorul de rezolutie, adica y= :: sin(x).
Aceasta reprezinta zona de nume globala si corespunde regiunii declarative la nivel de fisier.
Zonele de nume sunt deschise, adica putem adauga nume la zone existente.
Declaratia de utilizare adauga un nume la regiunea declarativa locala, împiedicând declararea altei variabile locale cu acelasi nume (si ascunzând variabila globala cu acelasi 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
}
Preview document
Conținut arhivă zip
- Tratarea exceptiilor.doc