Constructorul de copiere

In afara constructorilor si destructorilor predefiniti (default) compilatorul C++ asugura si un constructor de copiere default. Acest constructor de copiere este apelat de fiecare data cand se face o copiere a unui obiect.

Atunci cand se transmite un obiect prin valoare, fie ca parametru al unei functii fie ca valoare returnata de catre o functie, o copie temporara a obiectului este facuta. Daca obiectul este un obiect definit de utilizator, constructorul clasei este apelat.

Toti constructorii de copiere preiau un singur parametru, o referinta catre un obiect din aceeasi clasa. Este o buna idee folosirea unei referinte constante deoarece constructorii nu vor altera obiectul transmis. Spre exemplu

Cat(const Cat & theCat);

Aici constructorul Cat preia o referinta constanta catre un obiect de tip Cat deja creat. Scopul constructorul de copiere este executarea unei copy a obiectului theCAT.

Costructorul de copiere default copiaza fiecare variabila membru a obiectului transmis ca parametru in noul obiect. Se cheama ca se face o copiere inteligenta a membrilor. Cu toate ca aceasta este bine pentru variabilele membre obisnuite, pentru variabilele membre de tip pointer nu se poate afirma acelasi lucru. Variabilele pointer ale celor doua obiecte (cel original si cel clonat) vor pointa catre aceleasi zone de memorie, ceea ce poate constitui un avantaj sau o sursa de mari probleme atunci cand se elebereaza aceasta zona de memorie insa raman obiecte al caror membre de tip pointer pointeaza catre aceste zone.

Solutia la aceasta problema este construirea propriului constructor de copiere ca in exemplu urmator (cpy_cnst.cpp).

#include <iostream.h>

class CAT
{
public:
CAT(); // default constructor
CAT (const CAT &); // copy constructor
~CAT(); // destructor
int GetAge() const { return *itsAge; }
int GetWeight() const { return *itsWeight; }
void SetAge(int age) { *itsAge = age; }

private:
int *itsAge;
int *itsWeight;
};

CAT::CAT()
{
itsAge = new int;
itsWeight = new int;
*itsAge = 5;
*itsWeight = 9;
}

CAT::CAT(const CAT & rhs)
{
itsAge = new int;
itsWeight = new int;
*itsAge = rhs.GetAge();
*itsWeight = rhs.GetWeight();
}

CAT::~CAT()
{
delete itsAge;
itsAge = 0;
delete itsWeight;
itsWeight = 0;
}

int main()
{
CAT frisky;
cout << "frisky's age: " << frisky.GetAge() << endl;
cout << "Setting frisky to 6...\n";
frisky.SetAge(6);
cout << "Creating boots from frisky\n";
CAT boots(frisky);
cout << "frisky's age: " << frisky.GetAge() << endl;
cout << "boots' age: " << boots.GetAge() << endl;
cout << "setting frisky to 7...\n";
frisky.SetAge(7);
cout << "frisky's age: " << frisky.GetAge() << endl;
cout << "boot's age: " << boots.GetAge() << endl;
return 0;
}

Dupa executie pe ecran se obtine

frisky's age: 5
Setting frisky to 6...
Creating boots from frisky
frisky's age: 6
boots' age: 6
setting frisky to 7...
frisky's age: 7
boot's age: 6

 

Cornel Mironel Niculae, 2003-2004

04-Mar-2004