Sunteți pe pagina 1din 6

Constructorul de copier

Constructorul de copier este un constructor folosit pentru clonarea unui obiect instanțe clasei,
adică de exemplu a crea un obiect nou, copie câ t mai fidelă a unui obiect existent. Orice clasă C++
are constructor de copiere. În lipsa definirii de că tre programator explicit a constructorului de
copiere se creează la compilare constructor de copiere implicit.
Constructorul de copiere implicit inițializează toate câ mpurile obiectului nou cu valorile câ mpurilor
obiectului clonat. Acest mecanism poate conduce la crearea unui obiect nou avâ nd câ teva probleme
nedorite.
Exemplu:
Presupunem că un obiect prelucrează un fișier, de exemplu scrie mesaje în el. Un obiect creat cu
constructorul de copiere implicit va folosi același fișier. Cele 2 obiecte depunâ nd ambele mesaje în
același fișier. Este foarte probabil ca funcționalitatea unui astfel de obiect să fie gâ ndită pentru a
funcționa cu un fișier unic atașat acelui obiect.
Pentru ca obiectul-clonă să lucreze cu un alt fișier ar trebui să scriem noi constructorul de copiere
care va crea un alt fișier pentru obiectul-clonă . O situație similară ar fi atunci câ nd un obiect are
deschisă o conexiune cu o bază de date sau de internet și obiectul-clonă ar trebui să aibă o altă
conexiune creată decâ t a obiectului clonat.
Cea mai mare problemă apare atunci câ nd un obiect alocă dinamic memorie și adresele acestor
zone sunt reținute în câ mpurile obiectului. Constructorul de copiere implicit crează un nou obiect în
care câ mpurile pointer vor reține adresele de memorie alocată dinamic din obiectul clonat. Astfel,
cele 2 obiecte vor folosi în comun zone de memorie alocate dinamic. În cele mai multe situații acest
luctu este nedorit, adică fiecare obiect trebuie să aibă zone de memorie distincte alocate dinamic.
*CEVA DESEN*

Situația descrisă mai sus poate genera mai multe probleme:


1. Orice modificare a zonei de memorie alocate dinamic de că tre obiect este evident vizibilă și
în celă lalt obiect
2. Atunci câ nd unul dintre obiecte eliberează zona de memorie alocată dinamic, de exemplu la
distrugere, celă lalt obiect ră mâ ne fă ră zona de memorie alocată dinamic. Mai mult este
posibil ca la distrugerea celuilalt obiect să se încerce reeliberarea zonei de memorie alocată
dinamic. Ceea ce conduce inevitabil la eroare runtime.
În consecință , pentru a evita problemele de mai sus se procedează astfel: pentru obiectul nou creat
se alocă zone noi de memorie și informațiile din zonele alocate dinamic ale primului obiect se
copiază în zonele de memorie ale obiectului-clonă .
*ALT DESEN*
Constructorul de copiere poate fi explicit apelat de cître programator la crearea unui nou obiect, ca
orice constructor, însă în cele mai multe situații constructorul de copiere este apelat automat atunci
câ nd avem transmitere prin valoare a unor obiecte instanță clasei respective ca parametrii ai unei
funcții și atunci câ nd un obiect este returnat prin valoare ca valoare a funcției (aici există și
excepții).
//h
class polinom
{
int n; //grad
float* a; //coeficienți
public:
polinom(){n=-1;a=NULL;}
polinom(const polinom&); //constructor de copiere
friend ostream& operator<<(ostream&,polinom);
friend istream& operator>>(istream&,polinom&);
polinom operator+(polinom);
~polinom();
ostream&operator<<(ostream& fl, polinom p)
{
if(p.n<0)
throw “polinom neinitializat.”;
fl<<p.n;
for(int i=0;i<=n;i++)
fl<<” ”<<p.a[i];
return fl;
}
istream&operator>>(istream&fl,polinom&p)
{
fl>>p.n;
if(p.n<0)
throw “grad invalid.”;
if(p.a)
delete[] p.a;
p.a=new float[p.n+1];
for(int i=0;i<=p.n;i++)
fl>>p.a[i];
return fl;
}
};

//cpp
polinom::polinom(const polinom&)
{
if(p.n<0)
{
n=-1;
a=null;
return;
}
n=p.n;
a=new float[n+1];
for(int i=0;i<=n;i++)
a[i]=p.a[i];
}

polinom::~polinom()
{
if(a)
delete[]a;
}
polinom polinom::operator+(polinom p)
{
if(n<0||p.n<0)
throw “grad invalid.”;
polinom s;
if(n<=p.n)
{
s.n=p.n;
s.a=new float[s.n+1];
for(int i=n+1; i<=p.n;i++)
s.a[i]=p.a[i];
for(int i=0;i<=n;i++)
s.a[i]=a[i]+p.a[i];
}
else
{…………………..}
return s;
Constructorul de copiere îl recunoaștem prin faptul că are un singur parametru de tip referință
că tre clasa respectivă . Mai mult, acest parametru se declară ca fiind const.
Din cauză că parametrul p este transmis prin valoare la supraâ ncă rcarea operatorului << pentru el
este apelat constructorul de copiere. În implementarea operatorului ajungâ nd o clonă a celui de-al
doilea operand.
La suprîncă rcarea operatorului >> nu se folosește constructorul de copiere, al doilea parametru
fiind transmis prin referință .
La impelmentarea operatorului + primim parametrul p prin valoare, ceea ce înseamnă că se
apelează pentru el constructorul de copiere. Polinomul s este returnat prin valoare, ceeea ce ar
însemna că se apelează la returnarea lui s constructorul de copiere. Din cauză că variabila s, după
pă ră sirea operatorului + iese din stiva de execuție, obiectul s distrugâ ndu-se, compilatorul în
această situație face o optimizare care constă în returnarea obiectului s în locul clonei acestuia.
polinom operator+(polinom);
~polinom();
Polinom operator=(polinom&);
//cpp
polinom polinom::operator=(polinom&p)
{
if(this==&p)
return *this; //p=p
if(a) delete[]a;
n=p.n;
if(!p.a)
a=NULL;
else
{
a=new float[n+1];
for(int i=0;i<=n;i++)
a[i]=p.a[i];
}
return *this;
}
La apelui operatorului =, constructorul de copiere va fi apelat o singură dată, la momentul în care se
ajunge la return *this. Deoarece se dorește returnarea unei copii a obiectului curent și obiectul
curent nu se distruge așa cum s-a întâmplat la operatorul +, unde s se distruge.
Primul if de la implementarea lui = evită situația specială în care operatorul = ar fi apelat sub forma
p=p.
Temă : operatorul + între un real și un polinom
- Sub toate cele 3 forme
*polinom cu polinom, real cu polinom, polinom cu real
/polinom cu real, polinom cu polinom rezultâ nd câ tul împă rțirii
%polinom cu polinom rezultâ nd restul împă rțirii
==
!=
! returnează gradul polinomului

S-ar putea să vă placă și