Moderators NEFERPITOU Postat Decembrie 3, 2024 Moderators Postat Decembrie 3, 2024 ** Ce reprezinta si importanta acestuia in paradigma OOP ** Un destructor reprezinta o functie "speciala" care se ocupa de eliberarea memoriei alocate de membrii unei instante (Inchidem fisiere , diverse servicii etc.) . Practic , in constructor alocam memorie pentru membrii iar in destructor , le eliberam . ** Caracteristici ** Sunt membrii asemenea constructorilor , nu permit argumente si nu returneaza valori ; Se declanseaza , automat , la distrugerea obiectului (La iesirea din context sau la operatorul "delete") fara a fi solicitat explicit . (adica mentionat) ; NU poate fi constant sau static ; (Asemenea Constructorului) ; NU POT EXISTA MAI MULTI DESTRUCTORI (DOAR UNUL) !!! ** Nota 1 : NU EXISTA DESTRUCTOR IN majoritatea Limbajelor (cu paradigma OOP) precum C# , Java , Python etc. , deoarece au un sistem dedicat pentru gestionarea resurselor alocate !!! ** Nota 2 : E FOARTE IMPORTANT SA FOLOSIM DESTRUCTORI , de fiecare data , PENTRU A ELIBERA TOATA MEMORIA REZIDUALA ("Memory Leak") !! ** Declaratie Destructor ** ~<nume_clasa>(){ // Aici Eliberam Toata Memoria Reziduala } // De exemplu , daca avem clasa "Utilizator" , definim destructoru : ~Utilizator(){ // Continut Destructor } ** Exemplu de Utilizare Destructor ** 1. Sa presupunem ca avem o clasa "Utilizator" cu campurile : class Utilizator { private: // Sector Privat // Campuri unsigned id; // NUMAR NATURAL char* username; // SIR DE CARACTERE char* email; // SIR DE CARACTERE char* password; // SIR DE CARACTERE unsigned nrPosts; // NUMAR NATURAL bool isBanned; // E BANAT }; 2. Alocam si Initializam datele prin doi constructori : class Utilizator{ // Campuri ... public: // Sector Public /* * CONSTRUCTORI */ Utilizator() { // Constructor Default // Alocam si Initializam date cu informatii IMPLICITE (DEFAULT ) // Variabile cu Alocare Statica id = 0; nrPosts = 0; isBanned = false; // Variabile cu Alocare Dinamica atribuireSirCaractere(&username, "IMPLICIT"); atribuireSirCaractere(&email, "implicit@gmail.com"); atribuireSirCaractere(&password, "implicitParola"); } Utilizator(unsigned _id, const char* _username, const char* _email, const char* _password) // Constructor cu Parametrii Esentiali (Un utilizator NOU nu poate sa aiba ban sau posturi) { // Variabile cu Alocare Statica id = _id; // Preluam din parametru nrPosts = 0; // IMPLICIT 0 POSTURI LA CONSTRUCTIA UTILIZATORULUI isBanned = false; // NU E BANAT // Variabile cu Alocare Dinamica atribuireSirCaractere(&username, _username); atribuireSirCaractere(&email, _email); atribuireSirCaractere(&password, _password); } }; 3. Sa nu uitam de functia "atribuireSirCaractere" (Declarata inafara functiei) care ne permite sa alocam & atribuim siruri de caractere : void atribuireSirCaractere(char** target, const char* source) { size_t bufferString = strlen(source) + 1; *target = new char [bufferString]; strcpy_s(*target, bufferString, source); } 4. Adaugam cativa getteri si setteri pentru afisare /* Getteri & Setteri */ const unsigned const getId() { return id; } const char* const getUsername() { return username; } const char* const getEmail() { return email; } const char* const getPassword() { return password; } const unsigned const getnrPosts() { return nrPosts; } const bool const getisBanned() { return isBanned; } // Setteri // NU Putem seta ID-ul cuiva void setNrPosts(const unsigned _nrPosts) { if (_nrPosts > 0) // doar daca numarul de Posturi e mai mare decat 0 { nrPosts = _nrPosts; } } void setIsBanned(const bool _isBanned) { isBanned = _isBanned; } void setUsername(const char* _username) { // Realocam spatiu pentru Nume Utilizator delete username; // Delete Existing Memory // Allocate New Memory atribuireSirCaractere(&username, _username); } void setEmail(const char* _email) { // Realocam Spatiu pentru Mail delete email; // Delete Existing Memory // Allocate New Memory atribuireSirCaractere(&email, _email); } void setPassword(const char* _password) { // Realocam Spatiu pentru Parola delete password; // Delete Existing Memory // Allocate New Memory atribuireSirCaractere(&password,_password); } 5. Adaugam Destructorul clasei : class Utilizator{ // Restul Clasei... // Destructor ~Utilizator() { cout << "\nDESTRUCTORUL utilizatorului " << username << " A FOST DECLANSAT CU SUCCES !!\n"; // Eliberam memoria ocupata de variabilele alocate dinamic delete username; delete email; delete password; // Setam Pointeri pe NULL username = nullptr; email = nullptr; password = nullptr; } }; 6. In functia principala (main) , declaram obiecte noi , le initializam si vedem actiunea destructorului : #include <iostream> // Pentru OBIECTELE std::cout , std::cin using namespace std; // Pentru a substitui "std::cout" cu "cout" , "std::cin" cu "cin" etc. void atribuireSirCaractere(char** target, const char* source) { /// detalii .. } class Utilizator{ // detalii .. }; /* Functie Personalizata pentru a afisa Obiectele */ void objectToString(Utilizator& const user) // Transferam obiectul prin referinta constanta) { // DOAR AFISAM CAMPURILE OBIECTULUI cout << "\n{" << "\nID Utilizator : " << user.getId() << " ,\n" << "Nume Utilizator : " << user.getUsername() << " ,\n" << "Adresa Mail : " << user.getEmail() << " ,\n" << "Parola Utilizator : " << user.getPassword() << " ,\n" << "Numar Posturi : " << user.getnrPosts() << ", \n" << "Este Banat : " << (user.getisBanned() ? "ESTE BANAT" : "NU ESTE BANAT") << " ,\n}"; } int main() { Utilizator userVasile(1, "Vasile", "vasile@gmail.com", "vasileParola"); // Alocati static Utilizator* userIon = new Utilizator(2, "Ion", "ion@gmail.com", "ionParola"); { // Scenariul 1 : Obiect alocat static si construit sub un context , loop etc. Utilizator defaultUser; // Setam date noi defaultUser.setUsername("Alin"); defaultUser.setEmail("alin@gmail.com"); defaultUser.setPassword("alinPassword"); defaultUser.setNrPosts(50); objectToString(defaultUser); // Afisam Obiectul // Iesim din Context (La sfarsitul acestor acolade , obiectul iese din context si declanseaza destructorul ) } // Scenariul 2 : Obiect alocat static si construit in main objectToString(userVasile); // Afisam Vasile // Scenariul 3 : Obiect alocat dinamic si construit in main objectToString(*userIon); // Afisam Ion delete userIon; // Aici se declanseaza destructorul ION userIon = nullptr; return 0; // Aici se declanseaza destructorul VASILE (La finalul functiei/programului) } 6. Dand executie , vom avea urmatorul rezultat : { ID Utilizator : 0 , Nume Utilizator : Alin , Adresa Mail : alin@gmail.com , Parola Utilizator : alinPassword , Numar Posturi : 50, Este Banat : NU ESTE BANAT , } DESTRUCTORUL utilizatorului Alin A FOST DECLANSAT CU SUCCES !! { ID Utilizator : 1 , Nume Utilizator : Vasile , Adresa Mail : vasile@gmail.com , Parola Utilizator : vasileParola , Numar Posturi : 0, Este Banat : NU ESTE BANAT , } { ID Utilizator : 2 , Nume Utilizator : Ion , Adresa Mail : ion@gmail.com , Parola Utilizator : ionParola , Numar Posturi : 0, Este Banat : NU ESTE BANAT , } DESTRUCTORUL utilizatorului Ion A FOST DECLANSAT CU SUCCES !! DESTRUCTORUL utilizatorului Vasile A FOST DECLANSAT CU SUCCES !! SCENARIUL 1 : Observam ca destructorul obiectului "IMPLICIT" s-a declansat la sfarsitul acoladelor , unde a iesit din context ; SCENARIUL 2 : Destructorul obiectului "Ion" (alocat dinamic) s-a declansat , automat , la intalnirea cu operatorul "delete" . (Se distruge obiectul si iese din context) ; SCENARIUL 3 : Destructorul obiectului "Vasile" s-a declansat la sfarsitul programului (dupa ce am returnat 0 in "main") .
Postări Recomandate