Realizarea unei clone a unui obiect presupune crearea
unui obiect nou, cu existenta independenta de cel clonat, care ocupa in memorie
un spatiu distinct de cel clonat dar care are toate atributele si metodele
identice cu ale celui clonat.
Mecanismul urmator foloseste constructorul de copiere si o metoda declarata virtuala, care este
supracrisa in clasa derivata. Declararea virtuala este necesara pentru apelul
corect al metodelor: metoda Clone va fi cautata intai in clasa derivata,
indiferent de scenariu - fie ca variabila are tipul clasei de baza sau cel al
clasei derivate.
Stim ca o variabila initializata cu o instanta a clasei
derivate are si tipul clasei de baza (invers nu!)
Suprascrierea metodei implica prezervarea aceleiasi semnaturi (nume, argumente, tip de return) dar o implementare diferita in
clasa derivata.
Clasa de baza numita Base are un membru protected (pentru a putea fi
accesat prin constructorul de copiere si din clasa derivata), constructorul
explicit, constructorul de copiere, metoda virtuala Clone() ce va fi
suprascrisa in clasa Derivat. Destructorul clasei de baza
este declarat virtual.
Metodele getter din
ambele clase au rolul de a permite verificarea clonarii - daca s-a facut in mod corect, cu transmiterea informatiei din membrii protected si private
ai obiectului clonat la obiectul-clona.
De remarcat ca metoda Clone() intoarce, prin
definitie, un pointer la tipul Base.
Prin urmare, chiar daca este apelata metoda din clasa Derivat
(si se cloneaza obiectul apartinand
acestei clase), este necesara o operatie cast a pointerului (Base *) la tipul (Derivat
*), pentru a putea accesa
membrul obiectului clonat apartinand clasei derivate.
Codul urmator exemplifica aceste situatii: 1) clonarea unui obiect din clasa Derivat, generat dinamic
si 2) clonarea unui obiect din clasa Base. Spatiile alocate dinamic se
sterg la final cu operatorul delete.
// mecanismul de clonare
#include
<iostream>
using namespace std;
class Base
{
protected:
int
_p;
public:
Base(int p = 0) {_p = p;}
Base(const Base &src) {_p = src._p;}
virtual ~Base() {cout <<"Distrugerea instantei tip Base.\n";}
virtual Base * Clone() {cout << "\nAlpha!"; return new
Base(*this);}
int
Getp() {return _p;}
};
class Derivat : public
Base
{
int
_q;
public:
Derivat(int p = 0, int q = 0) : Base(p), _q(q) {}
Derivat(const Derivat &src) {_p = src._p; _q = src._q;}
~Derivat() {cout <<"Distrugerea instantei tip Derivat.\n";}
Base * Clone() {cout << "\nBeta!"; return new Derivat(*this);}
};
int main()
{
Base * ptr
= new Derivat(128, 1024);
Base *
ptr1 = ptr->Clone();
cout
<<"\n" <<ptr1->Getp();
cout
<<"\n" <<((Derivat*)ptr1)->Getq(); // cast la tipul (Derivat *)
cout
<<"\n";
Base *
ptr2 = new Base(64);
Base *
ptr3 = ptr2->Clone();
cout
<< "\n" <<ptr3->Getp();
cout
<<"\n\n";
delete
ptr; // este apelat destructorul clasei derivate
delete
ptr1; // este apelat destructorul clasei derivate
delete
ptr2;
delete
ptr3;
return 0;
}
No comments:
Post a Comment