Documente Academic
Documente Profesional
Documente Cultură
PCLP1 Capitolul12
PCLP1 Capitolul12
Tratarea excepiilor
Template-urile (abloanele) reprezint una dintre cele mai puternice
caracteristici ale limbajului C++. Acestea permit definirea, printr-un singur segment
de cod, a unei ntregi game de funcii suprancrcate template de funcie sau a unei
ntregi serii de clase template de clas. n acest capitol vom discuta cazul funciilor.
Putem scrie generic, de exemplu, un singur template de funcie pentru ordonarea
unui ir de elemente, iar funcia poate fi apelat pentru valori de diverse tipuri: int,
double etc.
Tratarea excepiilor este o metod care permite programatorilor s scrie
programe mai robuste, mai clare i cu un grad mai mare toleran la erori.
Programele pot fi concepute astfel nct s detecteze i s trateze erorile (excepiile)
care pot aprea n timpul rulrii, evitnd astfel ntreruperile neplanificate ale
aplicaiilor.
12.1
Template-uri de funcii
<iostream>
using std::cout;
using std::endl;
template< class T >
void PrintArray(const T *array, const int count)
{
for(int i = 0; i < count; i++)
cout << array[i] << " ";
cout << endl;
}
int main()
{
const int aCount = 5, bCount = 7, cCount = 6;
int a[aCount] = {1, 2, 3, 4, 5};
double b[bCount] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7};
char c[cCount] = "HELLO";
cout << "Tabloul a contine: " << endl;
PrintArray(a, aCount);
cout << "Tabloul b contine: " << endl;
PrintArray(b, bCount);
cout << "Tabloul c contine: " << endl;
PrintArray(c, cCount);
return 0;
}
Acest program afieaz:
Tabloul a contine:
1 2 3 4 5
Tabloul b contine:
1.1 2.2 3.3 4.4 5.5 6.6 7.7
Tabloul c contine:
H E L L O
Funcia template PrintArray declar un singur parametru formal de tip cu
numele T. Identificatorul T poate fi nlocuit cu orice alt identificator valid. Prin T se
definete generic tipul tabloului ale crui componente urmeaz s fie tiprite. Atunci
cnd compilatorul detecteaz n program un apel al funciei PrintArray, tipul
argumentului generic este nlocuit cu tipul parametrului actual i se creeaz o funcie
pentru tiprirea tabloului cu acest tip. Noua funcie este apoi compilat.
n exemplul de mai sus, sunt instaniate trei funcii PrintArray, cu argumente
de tip int, double i char.
Exemplu
Instanierea pentru tipul de dat int este:
void PrintArray(const int *array, const int count)
{
for(int i = 0; i < count; i++)
12.2
Tratarea excepiilor
Exist mai multe tehnici prin care pot fi tratate erorile care apar n timpul rulrii
unui program. Cea mai folosit este aceea de a introduce n program secvene de
cod adaptate prevenirii unor posibile situaii nedorite. Erorile sunt tratate n locul n
care apar n program. Avantajul acestei abordri este c persoana care citete codul
poate vedea modalitatea de prelucrare a erorii n vecintatea codului i poate
determina dac metoda de tratare a excepiei este implementat corect.
Dezavantajul este c prin aceast schem codul este oarecum poluat cu secvene
de procesare a erorilor i devine mult mai greu de citit de un programator care este
concentrat pe aplicaia nsi. Aceast metod face codul mult mai greu de neles i
de meninut.
Tratarea excepiilor n C++ permite programatorilor s nlture partea de tratare
a excepiilor din secvena principal de program. Stilul C++ de tratare a excepiilor
permite interceptarea tuturor excepiilor sau a tuturor excepiilor de un anumit tip.
Aceasta face programul mult mai robust, reducnd probabilitatea de ntrerupere
neplanificat a programului.
Tratarea excepiilor se folosete n situaia n care programul poate s i
continue rularea dup ce depete eroarea care provoac excepia.
blocuri catch. Fiecare bloc catch specific tipul excepiei pe care o poate detecta
i trata. Dac excepia se potrivete cu tipul parametrului unuia dintre blocurile
catch, se execut codul acelui catch. Dac nu este identificat niciun bloc catch
care s trateze eroarea, se apeleaz funcia predefinit terminate care la rndul ei
apeleaz n mod implicit funcia predefinit abort pentru ntreruperea programului.
Dac ntr-un bloc try nu se genereaz nicio excepie, programul ruleaz
ignornd blocurile catch asociate lui.
Exemplu
#include <iostream>
#include <stdexcept>
using std::cin;
using std::cout;
using std::endl;
using std::runtime_error;
double Fractie(int numarator, int numitor)
{
if(numitor == 0)
throw runtime_error("Numitorul este 0");
return static_cast<double>(numarator)/numitor;
}
int main()
{
int numar1, numar2;
double rezultat;
cout << "Introduceti doi intregi (EOF pentru a termina): ";
while(cin >> numar1 >> numar2)
{
try
{
rezultat = Fractie(numar1, numar2);
cout << "Valoarea fractiei este: " << rezultat << endl;
}
catch(runtime_error e)
{
cout << "A aparut urmatoarea exceptie: "
<< e.what() << endl;
}
cout << "Introduceti doi intregi (EOF pentru a termina): ";
}
cout << endl;
return 0;
}
Un exemplu de rulare a acestui program este urmtorul:
Introduceti doi intregi (EOF pentru a termina): 3 4
Valoarea fractiei este: 0.75
Introduceti doi intregi (EOF pentru a termina): 5 0
specificat numai n scopul potrivirii dintre blocul catch i tipul excepiei creia i este
destinat.
O excepie care nu este detectat apeleaz n mod implicit funcia
terminate() din biblioteca standard care, la rndul ei, termin programul prin
apelul funciei abort(). Programatorul poate schimba comportamentul funciei
terminate() facnd ca aceasta s apeleze o alt funcie. Numele noii funcii va fi
trimis ca parametru funciei set_terminate.
Un catch care este urmat ntre parantezele rotunde de trei puncte trateaz
toate excepiile.
Exemplu
catch(...)
Aceast opiune este plasat, de obicei, ca o ultim variant ntr-o serie de
blocuri catch. Un bloc try urmat de mai multe blocuri catch are un comportament
similar instruciunii switch care folosete o ramur case n funcie de valoarea
expresiei testate.
ThrowException();
cout << "Acest text nu este tiparit";
}
catch(exception e)
{
cout << "Exceptia tratata in main" << endl;
}
cout << "Programul continua dupa catch in main" << endl;
return 0;
}
Acest program afieaz:
Functia ThrowException
Exceptia tratata in ThrowException
Exceptia tratata in main
Programul continua dupa catch in main
Funcia ThrowException este apelat n blocul try din main. n blocul try
din funcia ThrowException este generat o excepie de tip exception care este
detectat imediat de blocul catch asociat acestui try. Aici, excepia este relansat,
fiind tratat n blocul catch din main.
Specificarea excepiilor
Lista excepiilor care pot fi generate de o funcie se poate specifica astfel:
int g(double h) throw(a, b, c)
{
//corpul functiei
}
Prin aceast list se restrnge gama excepiilor care pot fi declanate de funcia
g la tipurile a, b, c. Dac funcia genereaz o alt excepie dect cele listate, se
apeleaz automat funcia unexpected din biblioteca standard care, la rndul ei
apeleaz funcia terminate. Comportmenul funciei unexpected poate fi modificat
asemntor modului n care se intervine asupra funciei terminate, dar apelnd, de
data aceasta, funcia set_unexpected.
O funcie pentru care nu exist o astfel de list poate genera orice excepie.