Jump to content

[Programarea OrientatĂ Pe Obiecte - C++] Constructor de Copiere & Clone (Partea 1)


Soulrayne
 Share

Recommended Posts

OBIECTIV

 

Prin aceasta postare , dorim sa explicam si sa implementam , folosind codul de POO , conceptul de COPIERE(CLONARE) SUPERFICIALA (aka "Shallow Copy") a unui obiect !!

 

Clonarea Unui Obiect

 

CLONAREA/COPIEREA UNUI OBIECT reprezinta procedeul de COPIERE a informatiei (membrii clasei) dintr-un  obiect (instanta) EXISTENT intr-un obiect NOU (REPLICA) . 

Acum , ne intrebam de ce sa clonam un obiect , in ce circumstante avem nevoie de acest concept , cu ce ne ajuta ? Pe scurt , ne sprijina prin comoditate . Ne furnizeaza o copie a unui obiect fara sa afectam obiectul original ("COPII DEFENSIVE") .

 

Clonarea unui Obiect se poate efectua , valabil in toate limbajele de programare POO (Java,Python,JavaScript,C# etc.) , sub forma de copie : 

► "Superficiala" sau "Shallow Copy" ,  se initiaza membrii clasei din obiectul clona  ,  cu REFERINTELE din obiectul original . Pe scurt , orice modificare care survine asupra obiectului clona , VA AFECTA si OBIECTUL ORIGINAL !! (SUNT DEPENDENTE UNA DE CEALALTA)

► "Adanca" sau "Deep Copy" , se initiaza membrii clasei din obiectul clona , cu VALORILE din obiectul original FARA SA FIE DEPENDENTE UNA DE CEALALTA . Pe scurt , orice modificare a obiectului clona , NU VA AFECTA OBIECTUL ORIGINAL !! (SUNT INDEPENDENTE UNA DE CEALALTA)

 

Constructor de Copiere

 

Constructorul de copiere reprezinta al treilea tip de constructori , pe langa cel cu parametrii si implicit , si modalitatea de construire a clonelor . Aici se initializeaza membrii obiectului clona cu referintele/valorile membriilor clasei . 

 

// CONSTRUCTOR DE COPIERE -- FORMAT 

constructor_copiere(const NUME_CLASA& obiect_original)  // Primim ca parametru , REFERINTA OBIECTULUI ORIGINAL
{
    // AICI SE EFECTUEAZA CLONAREA OBIECTULUI ORIGINAL 
}

 

NOTA :  DE ASEMENEA , IN CONSTRUCTORUL DE COPIERE PUTEM FOLOSI LISTA DE INITIALIZARE A MEMBRIILOR !!! 

 

IMPLEMENTARE CLONA SUPERFICIALA

 

Adaugam un constructor de copiere , in cadrul clasei "Utilizator" : 

 

// user.h 

class User{

/// RESTU CODULUI 

User(const User& otherUser); // PREIA REFERINTA OBIECTULUI ORIGINAL (DECLARARE CONSTRUCTOR DE COPIERE)
};

 

+ Implementare : 

 

// User.cpp 

User::User(const User& originalObject)  // CONSTRUCTOR DE COPIERE (COPIERE SUPERFICIALA )
	: id{ originalObject.id }, nrPosts{ originalObject.nrPosts }, isBanned{originalObject.isBanned},
	username{ originalObject.username }, email{ originalObject.email }, password{originalObject.password}, 
	stringHandling{originalObject.stringHandling}
{
    //**** OBIECTE ISI IMPART REFERINTELE (POINTERI ISI IMPART REFERINTELE) 

	   /*
	   
	         OBIECT ORIGINAL                  OBIECT CLONA 
	     username    0xda34133     -->        username     0xda34133   (ISI IMPART ACEEASI ZONA DE MEMORIE)
                     "IONEL"                               "IONEL"     (AUTOMAT , ACEEEASI VALOARE)


		 ==> DACA NUMELE DE UTILIZATOR(EMAIL,STRINGHANDLER,PASSWORD) SE SCHIMBA IN OBIECTUL CLONA ,
		    ATUNCI VOR APAREA MODIFICARI SI IN CEL ORIGINAL 
	   */

}

 

In programul principal , vom initializa patru obiecte cu tipuri diferite de constructori (cu parametrii , implicit si 2 de copiere) si le vom afisa : 

 

// entrypoint.cpp

#include "User.h" // Includem Clasa de Utilizatori 


int main()
{
	User *user3, *user4; 

	{
		User user1,
			user2("Vasile", "vasile@gmail.com", "vasileparola"); // Declaram doua instante (una cu constructoru implicit + constructor cu parametrii )

		user1.setUsername("IONEL");

		// PRODUCEM 2 CLONE 
	
		user3 = new User(user1); // Clonam Obiectul 1 
		user4 = new User(user2);  // Clonam Obiectul 2 

		// VIZUALIZAM OBIECTELE ATUNCI CAND OBIECTELE ORIGINALE SUNT IN CONTEXT 

		user1.objectToString();
		user2.objectToString();

		std::cout << " AFISAM CLONE IN INTERIOURUL CONTEXTULUI :  \n";

		user3->objectToString(); // Clona Utilizatorului 1 
		user4->objectToString(); // Clona Utilizatorului 2 

		std::cout << std::endl; // DINSTANTIEM CU O LINIE CELE DOUA VIZUALIZARI  
	}

	// AFISAM CLONELE ATUNCI CAND OBIECTELE ORIGINALE AU IESIT DIN CONTEXT (S-A APELAT DESTRUCTORUL)
	std::cout << " AFISAM CLONE IN AFARA CONTEXTULUI (CAND OBIECTUL ORIGINAL A IESIT DIN CONTEXT) :  \n";
    
	user3->objectToString(); // Clona Utilizatorului 1 
	user4->objectToString(); // Clona Utilizatorului 2 
    
    return 0;
}

 

Si primim ca rezultat : 

 

{
ID Utilizator : 0 ,
Nume Utilizator : IONEL ,
Adresa Mail : BINE AI VENIT PE COMUNITATEA BZONE!!! ,
Parola Utilizator : BINE AI VENIT PE COMUNITATEA BZONE!!! ,
Numar Posturi : 0,
STATUS BANAT : NU ESTE INTERZIS PE BZONE!!,
 }
{
ID Utilizator : 1 ,
Nume Utilizator : Vasile ,
Adresa Mail : vasile@gmail.com ,
Parola Utilizator : vasileparola ,
Numar Posturi : 0,
STATUS BANAT : NU ESTE INTERZIS PE BZONE!!,
 }
 
 AFISAM CLONE IN INTERIOURUL CONTEXTULUI :

{
ID Utilizator : 0 ,
Nume Utilizator : IONEL ,
Adresa Mail : BINE AI VENIT PE COMUNITATEA BZONE!!! ,
Parola Utilizator : BINE AI VENIT PE COMUNITATEA BZONE!!! ,
Numar Posturi : 0,
STATUS BANAT : NU ESTE INTERZIS PE BZONE!!,
 }
{
ID Utilizator : 1 ,
Nume Utilizator : Vasile ,
Adresa Mail : vasile@gmail.com ,
Parola Utilizator : vasileparola ,
Numar Posturi : 0,
STATUS BANAT : NU ESTE INTERZIS PE BZONE!!,
 }
 
 AFISAM CLONE IN AFARA CONTEXTULUI (CAND OBIECTUL ORIGINAL A IESIT DIN CONTEXT) :

{
ID Utilizator : 0 ,
Nume Utilizator : ŢŢŢŢŢŢŢŢŢŢ ,  // ZONA INVALIDA DE MEMORIE 
Adresa Mail : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE 
Parola Utilizator : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ , // ZONA INVALIDA DE MEMORIE 
Numar Posturi : 0,
STATUS BANAT : NU ESTE INTERZIS PE BZONE!!,
 }
{
ID Utilizator : 1 ,
Nume Utilizator : ŢŢŢŢŢŢŢŢŢŢŢ ,  // ZONA INVALIDA DE MEMORIE 
Adresa Mail : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ ,  // ZONA INVALIDA DE MEMORIE 
Parola Utilizator : ŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢŢ ,  // ZONA INVALIDA DE MEMORIE 
Numar Posturi : 0,
STATUS BANAT : NU ESTE INTERZIS PE BZONE!!,
 }

 

NOTA : TOTUSI , EXISTA O PROBLEMA CU ACEST PROCEDEU DE CONSTRUCTIE A CLONEI . De ce ? Daca se impart aceleasi zone de memorie , riscam sa accesam adrese invalide , astfel daca apelam destructorul pentru obiectele clone : 

 

// entryPoint.cpp

int main()
{
// Restu Codului 
delete user3, user4;  // AICI VOM PRIMI EROARE PENTRU CA ELIBERAM ZONE INEXISTENTE DE MEMORIE 
}

 

DIN ACEASTA CAUZA , SE PREFERA CELALALT TIP DE CONSTRUCTIE , PE CARE L VOM DISCUTA IN TUTORIALUL URMATOR !! 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.