lucrare de laborator nr. 1
Tema: Constructorul – funcţie de iniţializare a obiectelor clasei
Scopul lucrării:
·
Studierea principiilor de definire şi utilizare a
constructorilor
·
Studierea principiilor de definire şi utilizare a
destructorilor
·
Studierea tipurilor de constructori
Noţiuni de bază
Argumentarea necesităţii
Una din cele mai răspîndite
erori de programare (în orice limbaj) constă în utilizarea obiectelor fără
iniţializare anterioară, aşa precum nu toate limbajele asigură iniţializare
automată. Desigur, poate fi definită funcţia de iniţializare şi de distrugere a
obiectului:
class Book{
char *author;
int year;
int pages;
public:
void Init(char*,
int, int);
void Destroy();
};
void Book::Init(char* a, int y, int p){
author = new
char[strlen(a)+1];
strcpy(author,a);
year=y;
pages=p;
}
void Book::Destroy(){
delete[] author;
}
În acest exemplu, însă,
nimeni nu garantează că iniţializarea va avea loc, sau că va fi eliberată
memoria alocată. Alt neajuns al exemplului dat constă în pericolul scurgerii de
memorie, deoarece funcţia de iniţializare poate fi apelată de nenumărate ori. De
asemenea se poate bloca sistemul din cauza utilizării eronate a memoriei
dinamice, motivul fiind apelul funcţiei Destroy fără iniţializare.
Definire şi utilizare
Pentru a evita această
eroare, C++ asigură mecanismul de iniţializare automată pentru clasele definite
de utilizator – constructorul clasei. Iar pentru operaţiile de distrugere – destructorul clasei.
Constructorul – este o
funcţie membru specială, de acelaşi nume cu numele clasei, care se apelează
automat la crearea obiectului de tipul clasei. Constructorul nu returnează nici
un rezultat, chiar nici void. Compilatorul
garantează apelarea unică a constructorului pentru un singur obiect.
Destructorul – este o
funcţie membru specială, care se apelează automat la distrugerea obiectului.
Numele unui destructor este numele clasei precedat de caracterul „~”.Compilatorul
garantează apelarea unică a destructorului pentru un singur obiect. Un
destructor nu are parametri, de aceea nu poate fi supraîncărcat, şi el este
unic pentru o clasă.
Pentru un obiect local,
destructorul se apelează cînd controlul programului iese din domeniul lui (se
iese din blocul în care este declarat). Obiectele dinamice nu pot fi distruse
automat. Distrugerea se realizează de către programator prin intermediul
operatorului delete, care apelează,
propriu zis, destructorul.
Fie un exemplu analogic cu
cel precedent, utilizînd constructorul şi destructorul:
class
Book{
char
*author;
int
year;
int
pages;
public:
Book(char*, int, int);
~Book();
};
Book::Book(char*
a, int y, int p){
cout<< „Constructor”<<endl;
author = new char[strlen(a)+1];
strcpy(author,a);
year=y;
pages=p;
}
Book::~Book(){
cout<<”Destructor<<endl;
delete[] author;
}
void
main(){
Book b(“Stroustrup”,2000,890);
// Book b1; //
încercarea de a crea obiectul fără apelul //constructorului duce la erori
Book* ptr = new
Book(“Lippman”,1996, 1200);
// crearea dinamică a obiectului
delete ptr;
// în acest caz
eliberarea memoriei se realizează de //către programator
}
// aici se apelează
automat destructorul pentru b.
Tipurile constructorilor
Există patru tipuri de
constructori: implicit, de copiere, de conversie a tipului şi general. Această
clasificare este bazată pe regulile de definire şi utilizare a constructorilor.
·
Constructorul implicit – constructor fără parametri,
sau constructor cu toţi parametrii impliciţi.
·
Constructorul de copiere – constructor care are ca
parametru referinţă la obiectul clasei respective. Constructorul de copiere
poate avea şi alţi parametri care însă trebuie să fie impliciţi.
·
Constructorul
de conversie a tipului - constructorul,
care transformă un tip de obiect în altul.
·
Constructorul general – constructorul care nu
corespunde categoriilor enumerate mai sus.
Fie exemplul:
class Book{
char *author;
int year;
int pages;
public:
Book(); //
constructor implicit
Book(const
Book&); // constructor de copiere
Book(const
char*); // constructor de conversie a
tipului
Book(char*, int,
int); // constructor general
...
};
...
void main(){
Book
b(“Stroustrup”,1997,890); // general
Book b1 = b, b11(b); // de copiere
Book b2 =
“Stroustrup”, b21(“Bjarne”);
// de schimbare a
tipului
Book b3; // implicit
}
Constructori generaţi de
compilator. Interacţiunea lor cu constructorii definiţi de utilizator
Prezenţa constructorilor nu
este obligatorie. Se pot defini clase şi fără constructori. În acest caz,
compilatorul C++ generează în mod automat un constructor implicit şi de
copiere.
Constructorul implicit generat
nu realizează absolut nimic, iar constructorul de copiere generat automat implică
copierea bit cu bit, ceea ce nu întotdeauna este satisfăcător. În cazul
definirii unui constructor de către utilizator se generează automat numai
constructorul de copiere.
Recomandări
Fiecare clasă trebuie să
conţină constructori. Dacă clasa conţine elemente pointeri trebuie neapărat să
se supraîncarce constructorul de copiere, care se utilizează pentru crearea
copiilor obiectului, la apelul obiectului în funcţie. Motivul supraîncărcării
constructorului de copiere constă în necesitatea utilizării acţiunilor
suplimentare în comparaţie cu algoritmul standard de copiere, deoarece se poate
întîmpla ca două obiecte diferite să refere una şi aceeaşi memorie, ceea ce
poate duce la pierderea informaţiei şi la erori în sistemul de operare.
Exemplu de constructori de
copiere:
Book::Book(const Book& b){
author = new char[strlen(b.author)+1];
strcpy(author, b.author);
year = b.year;
pages = b.pages;
}
Constructorii trebuie să
utilizeze mecanisme numite iniţializatori (lista de iniţializare). Această
regulă contribuie la evitarea cheltuielilor necesare pentru iniţializarea
cîmpurilor clasei, deoarece la execuţia constructorului cîmpurile trebuie să
fie deja iniţializate, iar la execuţia iniţializatorilor – nu.
Book::Book(const
Book& b): year(b.year),pages(b.pages),
author(new char[strlen(b.author)+1])
{
strcpy(author,
b.author);
}
// apelul funcţiei strcpy a rămas în afara
iniţializatorului.
În cazul utilizării
tabloului de obiecte se defineşte în mod obligatoriu un constructor implicit,
care se apelează pentru iniţializarea elementelor tabloului.
Întrebări de control:
1. Explicaţi termenul
de iniţializare.
2. Ce cuvinte cheie se
utilizează pentru definirea constructorului şi a destructorului?
3. Poate oare un
constructor să returneze o valoare?
4. Pot oare să existe
clase fără constructori?
5. Cîţi constructori
poate conţine o clasă? Dar destructori? De ce?
6. Enumeraţi tipurile
de constructori?
7. Cum se apelează un
constructor?
8. De ce este nevoie de
definit un constructor de copiere?
9. De ce este nevoie de
definit un constructor de conversie a tipului?
10. În ce cazuri se
apelează constructorul de copiere? Care este sintaxa apelului?
11. Ce sunt listele de
iniţializare (iniţializatori)?
12. În care caz se
defineşte obligatoriu constructorul implicit?
lucrare
de laborator nr. 1
Sarcina
Varianta 1
Să se creeze clasa Date – dată cu cîmpurile: zi(1-28..31),
lună(1-12), an (numere întregi). Să se definească constructorii; funcţiile
membru de setare a zilei, lunii şi anului; funcţiile membru de returnare a
zilei, lunii, anului; funcţiile de afişare: afişare tip „ 6 iunie 2004” şi
afişare tip „6.06.2004”. Funcţiile de setare a cîmpurilor clasei trebuie să
verifice corectitudinea parametrilor primiţi.
Varianta 2
Să se creeze clasa Time – timp cu cîmpurile: ore (0-23),
minute (0-59), secunde (0-59). Să se definească constructorii, funcţiile membru
de setare a timpului; de returnare a orei, minutelor şi secundelor; funcţiile
de afişare conform şablonului: „ora 17 şi 18 minute şi 4 secunde” şi „5 p.m. 18
minute 4 secunde”. Funcţiile de setare a cîmpurilor clasei trebuie să verifice
corectitudinea parametrilor primiţi.
Varianta 3
Să se creeze clasa Vector,
care se compune dintr-un pointer spre float
şi din numărul de elemente. Să se definească constructorii: implicit, de
copiere şi cu un parametru. Să se definească destructorul, funcţiile de
iniţializare a unui vector, de setare/ modificare a dimensiunii vectorului, de
acces la elementele vectorului, de calcul a modulului unui vector. În funcţia main să se realizeze adunarea a doi
vectori.
Varianta 4
Să se creeze clasa File – fişier, care conţine informaţia
despre numele complet al fişierului şi anexa de asociere (doc – Word, psd –
Photoshop, etc.), utilizînd memoria dinamică, mărimea, data şi timpul creării.
Să se definească toi constructorii. Constructorul de schimbare a tipului are
parametrul – numele de fişier. Să se definească funcţiile de redenumire a
fişierului, de transfer în alt directoriu şi de modificare a anexei de
asociere.
Varianta 5
Să se creeze clasa Document – document, care conţine
informaţia despre denumirea, tema, autorul documentului utilizînd memoria
dinamică; numărul de pagini, data şi timpul ultimei redactări. Să se definească
toţi constructorii. Constructorul de schimbare a tipului are ca parametru
denumirea documentului. Să se definească funcţiile de modificare a temei, datei
ultimei redactări ş. a.
Varianta 6
Să se creeze clasa Image – imagine, care conţine următoarea
informaţie: denumirea fişierului, formatul de compresie, dimensiunile imaginii,
dimensiunea în octeţi, compresia (în %). Să se definească toţi constructorii.
Constructorul de schimbare a tipului are ca parametru denumirea fişierului. Să
se definească funcţiile de modificare a denumirii de fişier, a formatului, a
dimensiunii ş. a.
Varianta 7
Să se creeze clasa Vector,
care se compune dintr-un pointer spre int
şi din numărul de elemente. Să se definească constructorii: implicit, de
copiere şi cu un parametru. Să se definească destructorul, funcţiile de
iniţializare a unui vector, de setare/ modificare a dimensiunii vectorului, de
acces la elementele vectorului, de calcul a modulului unui vector. În funcţia main să se realizeze adunarea a doi
vectori.
Varianta 8
Să se creeze clasa String – şir, utilizînd memoria
dinamică. Să se definească constructorii: implicit, de copiere şi cu un
parametru – pointer spre un şir de tip char.
Să se definească funcţiile de atribuire a unui şir la altul, de comparaţie, de
căutare a unui subşir, de numărare a simbolurilor ş. a.
Varianta 9
Să se creeze clasa Discipline - disciplină, care conţine
informaţia despre denumirea obiectului, numele profesorului, numărul de ore la
disciplină şi forma de susţinere (examen sau colocviu). Să se utilizeze memoria
dinamică pentru setarea cîmpurilor textuale. Să se definească constructorii:
implicit, de copiere şi cu un parametru – denumirea disciplinei. Să se definească
funcţiile de schimbare: a profesorului, a numărului de ore şi a formei de
susţinere.
Varianta 10
Să se creeze clasa Soft – fişier, care conţine informaţia
despre numele complet al fişierului şi anexa de asociere (doc – Word, psd –
Photoshop, etc.), utilizînd memoria dinamică, mărimea, data şi timpul creării.
Să se definească toi constructorii. Constructorul de schimbare a tipului are
parametrul – numele de fişier. Să se definească funcţiile de redenumire a
fişierului, de transfer în alt directoriu şi de modificare a anexei de
asociere.
Varianta 11
Să se creeze clasa Group – grupa, care conţine informaţia
despre codul grupei, specialitatea, numărul de studenţi, curatorul grupei şi
anul de studii. Să se utilizeze memoria dinamică pentru setarea cîmpurilor textuale.
Să se definească: toate tipurile de constructori; funcţiile de schimbare a
curatorului şi a numărului de studenţi. Să se definească funcţia de setare a
anului de studii în aşa fel, încît valoarea acestui cîmp să poată fi mărită şi
să nu depăşească cifra 5.
Varianta 12
Să se creeze clasa Set – mulţimea numerelor întregi,
utilizînd memoria dinamică. Să se definească constructorii: implicit şi de
copiere. Să se definească funcţiile: de adăugare a unui element nou în mulţime;
de determinare a apartenenţei elementului la mulţime; de adunare, scădere şi
intersecţie a două mulţimi.
Varianta 13
Să se scrie un program care să
definească un nou tip de variabile - tipul complex şi să construiască funcţii adecvate pentru
operaţiile de bază cu acest tip de date (adunare, scădere, înmulţire, calculul
modulului numărului complex).
Varianta 14
Scrieţi un program care efectuează următoarelor
operaţii asupra unităţilor băneşti (de exemplu, lei, bani):
–
adunarea,
–
înmulţirea cu un coeficient,
–
scăderea,
–
împărţirea la un coeficient,
–
valoarea numerică a unităţilor băneşti să se
tipărească cu cuvinte.
Varianta 15
Scrieţi un program care efectuează următoarele
operaţii asupra numerelor fracţionare:
– transformarea unui
număr fracţionar compus într-o fracţie supraunitară,
–
adunarea numerelor fracţionare,
–
înmulţirea numerelor fracţionare,
–
scăderea numerelor fracţionare,
–
împărţirea numerelor fracţionare.
Varianta 16
Scrieţi un program care efectuează următoarele
operaţii asupra unităţilor de lungime (de exemplu, metri, centimetri,
milimetri):
– adunarea,
– înmulţirea cu un
coeficient,
– scăderea,
– împărţirea la un
coeficient,
– valoarea numerică a
unităţilor de lungime să se tipărească cu cuvinte.
Varianta 17
Scrieţi un program care efectuează următoarele
operaţii asupra unităţilor de greutate (de exemplu, tone, kilograme, grame):
–
adunarea,
–
înmulţirea cu un coeficient,
–
scăderea,
–
împărţirea la un coeficient,
–
valoarea numerică a unităţilor de greutate să se
tipărească cu cuvinte.
Varianta 18
Scrieţi un program care efectuează următoarele
operaţii asupra unităţilor de timp (de exemplu, anul, luna, ziua, ceasul,
minuta, secunde):
–
adunarea,
–
înmulţirea cu un coeficient,
–
scăderea,
–
împărţirea la un coeficient,
–
valoarea numerică a unităţilor de timp să se
tipărească cu cuvinte.
Niciun comentariu:
Trimiteți un comentariu