- •Programare orientată pe obiecte
- •§1. Principiile programării orientate pe obiecte.
- •§3. Constructori şi destructori.
- •8) Aceste mesaje apar după ce se termină lucrul programului.
- •§4. Operaţii de intrare/ieşire a informaţiei.
- •§5. Moştenire simplă.
- •§6. Moştenire multiplă
- •§7. Moştenirea pe mai multe niveluri. Clase virtuale
- •§9. Definirea şi utilizarea referinţelor
- •§10. Tablouri de obiecte. Pointeri şi referinţe la obiecte. Pointeri la membrii clasei
- •§11. Dirijarea dinamică a memoriei
- •§12. Constructor de copiere
- •§13. Funcţii prietene şi clase prietene
- •§14. Supraîncărcarea operatorilor
- •§15. Supraîncărcarea operatorilor prin funcţii prietene
- •§16. Supraîncărcarea unor operatori speciali
- •Operatorii de incrementare şi decrementare
- •Operatorii de inserţie şi extragere
- •Operatorul indice
- •Operatorul funcţie
- •Operatorii new şi delete
- •Operatorul virgulă
- •Operatorul de conversie
- •§17. Funcţii-şablon şi clase-şablon
- •§18. Realizarea conceptului de polimorfism
- •§19. Clase abstracte
- •§20. Membrii statici ai clasei
- •§23. Tratarea excepţiilor
- •Bibliografie
§12. Constructor de copiere
Orice clasă chiar dacă nu are un constructor de copiere definit explicit, are unul care este un constructor de copiere creat implicit de către compilator. Constructorul de copiere implicit face copierea binar cu binar a informaţiei dintr-un obiect creând un obiect nou. Dar un astfel de mecanism de obţinere a obiectelor-copii poate duce la erori grave. Acest fapt se poate întâmpla când clasa, în baza căreia sunt create obiecte, conţine pointeri care punctează la careva fragmente de memorie alocate dinamic. Dacă vor fi create copii ale unui obiect de acest tip prin metoda constructorului de copiere implicit, atunci vor exista mai multe obiecte care au asociate acelaşi fragment de memorie:
Dacă unul dintre aceste obiecte va fi nimicit, fragmentul de memorie asociat va fi eliberat şi atunci obiectele rămase vor arăta la un fragment de memorie inexistent. Dacă vor fi efectuate operaţii în cadrul acestui fragment de memorie, ele vor genera erori.
Constructorul de copiere este apelat în următoarele situaţii posibile:
Definirea unei variabile de tip obiect, iniţializând-o în baza unui obiect existent;
Transmiterea de obiecte în calitate de parametri reali ai unei funcţii care are parametri fictivi de tip obiect. Fiecare obiect va genera o copie, creată cu ajutorul constructorului de copiere.
Funcţiile care returnează o valoare de tip obiect în momentul returnării valorii creează o copie a obiectului.
Erori de tipul celei descrise anterior pot fi obţinute uşor, de exemplu, la transmiterea unui obiect în calitate de parametru real la apelarea unei funcţii. Va fi creat un obiect-copie, care la terminarea funcţiei va fi nimicit. Astfel, obiectul transmis în calitate de parametru real va fi afectat serios.
Pentru a evita asemenea erori trebuie de definit în cadrul clasei un constructor de copiere, care ar schimba scenariul de lucru al constructorului de copiere implicit. Şi anume, obiectul-copie ar trebui să-şi aibă propria memorie asociată, care conţine informaţie similară cu memoria asociată obiectului, în baza căruia este creată copia:
Un constructor de copiere are un parametru fictiv de tip referinţă şi este descris în felul următor:
class nume_cl
{
. . .
nume_cl(nume_cl &ob);
. . .
};
iar implementarea lui poate fi descrisă astfel:
nume_cl::nume_cl(nume_cl &ob)
{
// instructiuni
}
Exemplu:
class tablou
{
int *date;
int dim;
public:
tablou(int d, int val);
tablou(tablou &t);
~tablou();
void modificaTablou();
void afisare();
};
//-----------------
tablou::talbou(int d, int val)
{
date=new int[d];
if(date!=NULL)
{
dim=d;
for(int i=0;i<dim;i++) date[i]=val;
}
else
dim=0;
}
//-----------------
tablou::tablou(tablou &t)
{
dim=t.dim;
date=new int[dim];
for(int i=0;i<dim;i++) date[i]=t.date[i];
}
//-----------------
tabou::~tablou()
{
delete[] date;
}
//-----------------
void tablou::modificaTablou()
{
date[0]=date[0]+11;
// mareste primul element cu 11
}
//-----------------
void tablou::afisare()
{
for(int i=0;i<dim;i++) cout<<date[i]<<’ ’;
cout<<endl;
}
//-----------------
void main()
{
tablou t1(15,0), t2(25,1);
t1.afisare();
t2.afisare();
tablou t3(t2);
t3.modificaTablou();
t3.afisare();
}
Deoarece, în acest exemplu, este creat un constructor de copiere explicit (corect), orice schimbări asupra obiectului t3 nu afectează obiectul t2 şi invers.
