Sunteți pe pagina 1din 9

Tratarea excepiilor

Programatorii adevrai trebuie s ia n calcul i posibilitatea de a crea programe robuste, care fac
fa att cerinelor specificate dar nerafinate suficient, ct i cerinelor nespecificate dar formulate
de utilizator, din diverse motive. Programele care au aceste caliti se numesc robuste.
Nu ne bazm pe atenia i buna pregtire a utilizatorului !
Pentru a face fa cerinelor legate de problema tratrii excepiilor (aa sunt numite n mod curent
erorile care apar n timpul execuiei programelor) anumite limbaje de programare ofer suport
adecvat. A include aici limbaje precum Delphi, C++, Java, Visual C.
Nu toate compilatoarele de C++ ofer suport pentru tratarea excepiilor, dar standardul ANSI C++
cere acest lucru n mod explicit. Compilatoarele din familia Borland ncepnd cu versiunea 4.0
ofer acest suport.
Esenialul din punctul de vedere al programatorului C++ este ca el s-i formeze abilitatea de a
scrie n jurul aplicaiilor cod C++ care ndeplinete funcia de handler de excepii.
Suportul sintactic C++ pentru tratarea excepiilor se rezum la trei cuvinte cheie, a cror semantic
preliminar o prezentm n Tabelul urmtor:
Cuvntul cheie
try
throw
catch

Semnificaie
Delimiteaz o poriune de cod n care se instituie
controlul sistemului asupra excepiilor n timpul rulrii.
Lanseaz o excepie de un anumit tip
Capteaz o excepie lansat

Forma de baz a tratrii excepiilor


Aadar, atunci cnd programele dumneavoastr efectueaz prelucrarea excepiilor, trebuie s
includei n cadrul unui bloc try instruciunile pe care dorii s le monitorizai n vederea unei
excepii. Dac execuia unei instruciuni se termin cu o eroare, trebuie s lansai o eroare
corespunztoare aciunii funciei n care se afl instruciunea. Programul plaseaz instruciunea
throw n cadrul blocului try-catch. Forma generalizat a blocului care capteaz i trateaz erorile
este:
try{
//blocul try
if(eroare) throw valoare_excepie;
}
catch (Tip_excepie Nume_variabil ){
//Prelucrarea excepiei
}
n cadrul acestei forme generalizate, valoarea valoare_excepie lansat trebuie s corespund
tipului Tip_excepie .

Scrierea unui handler de excepii simplu


Pentru a nelege mai bine semantica unui handler de excepii, studiai programul de mai jos.
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

#include <iostream.h>
void main()
{
cout<<"Start"<<endl;
try
{
cout<<"In interiorul blocului try"<<endl;
throw 100;
cout<<"Nu se va executa";
}
catch (int i)
{
cout<<"Am captat o excepie -- valoarea este:";
cout<< i <<endl;
}
cout<<"Sfarsit";
};
Programul de mai sus implementeaz un bloc try-catch simplu. n loc s se atepte ca programul
s eueze datorit unei erori, se utilizeaz instruciunea throw pentru lansarea erorii prezumtive.
Dup ce blocul try lanseaz eroarea, blocul catch o capteaz i prelucreaz valoarea transmis
de instruciunea throw. Este evident i din acest exemplu c mecanismul try-throw-catch ofer
suport pentru rezolvarea problemei tratrii excepiilor dar nu rezolv de la sine aceast problem.
Altfel spus, tratarea corect a excepiilor unui program este o problem de atitudine ca
proiectant i ca programator.

Lansarea excepiilor cu o funcie din cadrul blocului try


Atunci cnd programele apeleaz funcii din cadrul blocurilor try , C++ va transmite excepia
aprut ntr-o astfel de funcie n afara funciei dac nu exist un bloc try n interiorul funciei.
Exemplul de mai jos arat cum se petrec lucrurile ntr-o astfel de situaie.
#include <iostream>
void XHandler(int test)
{
cout<<"Inauntrul functiei XHandler, test are valoarea:"<<test<<endl;
if(test) throw test;
};
void main()
{
cout<<"Start:"<<endl;
try
{
cout<<"Inauntrul blocului try"<<endl;
XHandler(1);
XHandler(2);
XHandler(0);
}
catch(int i)
{
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

cout<<"Am captat o exceptie. Valoarea este:";


cout<<i<<endl;
};
cout<<"Sfarsit";
};

Plasarea unui bloc try intr-o funcie


Am vzut cum apare un bloc try n funcia principal a unui program. C++ permite blocuri try i n
alte funcii ale unui program diferite de funcia principal.
Atunci cnd se plaseaz un bloc try ntr-o funcie C++ reiniializeaz blocul de fiecare dat cnd
intrai se intr n acea funcie. Programul urmtor ilustreaz cele spuse.
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test) throw test;
}
catch(int i)
{
cout<<"Am captat exceptia nr.: "<<i<<endl;
}
};
void main()
{
cout<<"Start: "<<endl;
XHandler(1);
XHandler(2);
XHandler(0);
XHandler(3);
cout<< "Sfarsit";
};
Un comentariu pe marginea celor prezentate pn acum ar fi urmtorul: o instruciune catch se
execut numai dac programul lanseaz o excepie n cadrul blocului try situat imediat nainte. n
caz c o astfel de excepie nu se lanseaz blocul catch va fi ignorat.

Utilizarea mai multor instruciuni catch cu un singur bloc try


Pe msur ce tratrile excepiilor devin tot mai complexe, uneori este necesar i posibil ca un
singur bloc try s lanseze excepii de mai multe tipuri. n cadrul programelor dumneavoastr putei
construi un handler de excepii astfel nct s accepte captarea mai multor excepii. ntr-o astfel de
situaie sintaxa general este:
try
{
}

//instruciuni

Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

catch (tip1)
{
//tratare excepie 1
}
catch(tip2)
{
//tratare excepie 2
}
:
catch(tipn)
{
//tratare excepie n
}
Cu acest amendament sintactic deducem c instruciunile catch pot capta orice tip returnat, nu
numai tipurile de baz acceptate de C++. Acest "fenomen" este ilustrat n codul de mai jos.
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test==0)
throw test;
if(test==1)
throw "Sir de caractere";
if(test==2)
throw 121.25;
}
catch(int i)
{
cout<<"Am captat exceptia #:"<<i<<endl;
}
catch(char *sir)
{
cout<<"Am captat exceptia de tip sir de caractere:"<<sir<<endl;
}
catch(double d)
{
cout<<"Am captat exceptia #:"<<d<<endl;
}
};
void main()
{
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

Blocuri catch generice (utilizarea operatorului puncte de suspensie)


Programele scrise de dumneavoastr pot capta excepii din cadrul mai multor blocuri try (de
exemplu un bloc try care incapsuleaza mai multe functii care lanseaza exceptii diferite din blocuri
try diferite sau s utilizeze mai multe instruciuni catch ntr-un singur bloc try. C++ permite, de
asemenea, utilizarea operatorului puncte de suspensie () pentru a capta orice tip de eroare care
apare ntr-un singur bloc try. Sintaxa care permite captarea tuturor erorilor care apar ntr-un bloc try
este prezentat mai jos.
try
{
//Instructiuni
}
catch()
{
//tratarea exceptiei
}
Pentru exemplificare propun codul de mai jos.
#include <iostream.h>
void XHandler(int test)
{
try
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
catch()
{
cout<<"Am captat o exceptie"<<endl;
}
};
void main()
{
cout<<"Start:"<<endl;
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
Evident, prelucrrile din cadrul blocului catch generic trebuie s fie independente de tipul erorii.
Mecanismul captrii excepiilor explicite poate fi combinat cu mecanismul excepiilor generice ca n
exemplul de mai jos.
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

#include <iostream.h>
void XHandler(int test)
{
try
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
catch(int i)
{
cout<<"Am captat o exceptie de tip intreg"<<endl;
}
catch()
{
cout<<"Am captat o exceptie generica"<<endl;
}
};
void main()
{
cout<<"Start:"<<endl;
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};

Restrictionarea exceptiilor
Pe msur ce programele dumneavoastr devin mai complexe, ele vor apela frecvent funcii din
cadrul unui bloc try. Atunci cnd programele dumneavoastr apeleaz funcii dintr-un bloc try,
putei restriciona tipurile de excepii pe care funcia apelat le poate lansa. De asemenea putei
preveni lansarea oricrei excepii dintr-o anumit funcie.
Sintaxa pentru restricionare este:
tip_returnat nume_functie(lista_arg) throw(lista_tipuri )
{
//Cod functie
}
Sintaxa care inhib lansare oricrei excepii este:
tip_returnat nume_functie(lista_arg) throw()
{
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

//Cod functie

Este bine s subliniem c atunci cnd declarai o funcie cu clauza throw ea poate s lanseze doar
acele tipuri precizate n list. Dac funcia lanseaz orice al tip programul este abortat.
Un exemplu n continuare.
#include <iostream.h>
void XHandler(int test) throw(int, char, double)
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
void main()
{
cout<<"Start:"<<endl;
try
{
XHandler(0);
}
catch(int i)
{
cout<<"Am captat un intreg"<<endl;
}
catch(char c)
{
cout<<"Am captat un caracter"<<endl;
}
catch(double d)
{
cout<<"Am captat un double"<<endl;
}
cout<<"Sfarsit";
};

Relansarea unei excepii


n anumite situaii poate fi necesar s se relanseze o excepie din interiorul unui handler de
excepii. Dac relansai o excepie, C++ o va transmite unui bloc try exterior dac acesta exist.
Cea mai probabil situaie n care putei opta pentru aceast variant este atunci cnd dorii s
tratai o excepie n cadrul a dou programe handler distincte. Pentru mai mult claritate urmrii
exemplul de mai jos.
#include <iostream.h>
void XHandler(void)
{
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

try
{
throw "Salve";
}
catch(char *)
{
cout<<"Am captat char* in XHandler "<<endl;
throw;
}
void main()
{
cout<<"Start"<<endl;
try
{
XHandler();
}
catch(char *)
{
cout<<"Am captat char * in main"<<endl;
}
cout<<"Sfarsit";
};

Mod de utilizare a excepiilor


Toate elementele prezentate au ncercat s demonstreze c C++ are o atitudine activ fa de
problema tratrii excepiilor. Suportul oferit de C++ l ajut pe programator s defineasc un
comportament al programului cnd se produc evenimente anormale sau neateptate. O idee mai
pragmatic de utilizare a suportului C++ n situaii efective o putei desprinde din exemplul de mai
jos.
#include <iostream.h>
void div (double a, double b)
{
try
{
if(!b) throw b;
cout<<"a/b="<<a/b<<endl;
}
catch(double b)
{
cout<<"Nu se poate imparti la zero"<<endl;
}
}
void main()
{
double i,j;
do
{
cout<<Introduceti numaratorul (0 pentru stop):"<<endl;
cin i;
Programarea calculatoarelor C++

s.l.ing. Delia UNGUREANU

cout<<Introduceti numitorul
cin j;
div(i,j);
} while (i!=0);
};

Programarea calculatoarelor C++

:"<<endl;

s.l.ing. Delia UNGUREANU