LUCRARE DE LABORATOR NR. 1

 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 def­­­inire ş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: