Visualizzazione dei risultati da 1 a 9 su 9
  1. #1

    [C++]Utilizzo dei distruttori

    Salve a tutti, ho quasi finito un progetto, purtroppo non ho ben capito come, e quando č necessario usare i distruttori, riporto i file header del mio progetto e il main, poichč suppongo sia qui che debba usarli:

    Node.hpp
    codice:
    #ifndef NODE_HPP
    #define	NODE_HPP
    
    #include <string>
    #include <stdio.h>
    #include "Film.hpp"
    
    using namespace std;
    
    
    class Node
    {
            protected:
                Film* element;
                Node* next;
                Node* prev;
                
            public:
                Node();
                Node(Film* element);
                ~Node();
        
        
               Film* getElement();
               void setElement(Film* element);
               void setNext(Node* succ);
               Node* getNext();
               void setPrev(Node* p);
               Node* getPrev();
    };
    LinkedList.hpp

    codice:
    #ifndef LINKEDLIST_HPP
    #define	LINKEDLIST_HPP
    #include "Node.hpp"
    #include <string>
    #include <stdio.h>
    #include <vector>
    #include "Tokenizer.hpp"
    #include <algorithm>
    #include <sstream>
    #include <string.h>
    
    
    using namespace std;
    
    class LinkedList
    {
        
            protected:
                Node* header;
                Node* trailer;
                int size;
         
                
            public:
                LinkedList();
               ~LinkedList();
               
               int getSize();
               Node* isPresent(Film* f);
               void addNode(Film* element,unsigned n);
               void removeNode(Film* toRemove);
               Film* exitFilm(Film* f);
               void returnFilm(Film* f);
               string copieFilm(Film* f);
               vector<Film*> ListaFilmPerAnno(unsigned a);
               vector<Film*> ListaRemake();
               string search(string word, int mode);
               string listaCompleta();
               Film* objectFilm(string titolo);
               
              
               
    };
    
    #endif	/* LINKEDLIST_HPP */
    Distributore.hpp
    codice:
    #ifndef DISTRIBUTORE_HPP
    #define	DISTRIBUTORE_HPP
    
    #include "LinkedList.hpp"
    
    using namespace std;
    
    class Distributore
    {
        
            protected:
                LinkedList* distributore;
                int size;
         
                
            public:
                Distributore();
               ~Distributore();
               
               int getSize();
               void InserisciFilm(Film* f, unsigned c); 
               void EliminaFilm(Film* film);
               Film* EsceFilm(Film* f);
               void RitornaFilm(Film* f);
               string CopieFilm(Film* f);
               vector<Film*> ListaFilmPerAnno(unsigned a);
               vector<Film*> ListaRemake();
               string search(string word, int mode);
               string listaCompleta();
               Film* objectFilm(string titolo);
              
    };
    
    
    
    #endif	/* DISTRIBUTORE_HPP */
    Ora nel main se inserisco un' istruzione alla fine, richiamando il distruttore di Distributore, il programma va in loop, mi spiegate quando e come si invocano, usano i distruttori?

    Per richiamarlo nel main uso:
    codice:
     distr->~Distributore();
    implementato cosģ:

    codice:
    Distributore::~Distributore(){
        delete distributore;
    }

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Non devi essere tu a esplicitare la chiamata a un distruttore.
    I distruttori sono invocati automaticamente dal linguaggio quando:
    1) Un oggetto posto sullo stack esce di scope
    2) viene effettuato il delete di un puntatore
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Quindi basta implementarlo nel cpp e poi il main va scritto normalmente? La chiamata al istruttore non va mai fatta?

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Si.
    No.
    Il richiamo automatico di un distruttore č alla base di tutto il linguaggio e serve per eseguire il codice di pulizia (per meglio dire il resource cleaning) senza un richiamo esplicito.
    Esempio.
    codice:
    class Distributore
    {
        
            public:
                Distributore() { cout << "ctor" << endl; }
               ~Distributore() { cout << "dtor" << endl; }
    };
    
    int main ( /* etc */ ) {
    
        /* reduce scope */ {
            Distributore* p = new Distributore;
            delete p;
        }
    
        /* reduce scope */ {
            Distributore p;
        }
    
        cin.get();    
    }
    Compila ed esegui passo passo e vedi l'output.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    Ah d' accordo, lo eseguirņ domani perchč non ho il portatile....ma quindi comunque nel main quello che devo fare č fare la delete dei puntatori? Cioč il mio distributore č una linkedlist, nel distruttore nel cpp cosa devo scrivere? Come si implementa? E poi nel main si deve fare la delete dei puntatori alla fine del programma?

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da Darčios89
    nel main quello che devo fare č fare la delete dei puntatori?
    Solo dei puntatori che allochi nel main, ne uno di pił ne uno di meno.

    Cioč il mio distributore č una linkedlist, nel distruttore nel cpp cosa devo scrivere?
    Il tuo distributore ha una linkedlist: č diverso.
    Devi implementare il distruttore di linkedlist in modo che provveda a eliminare i nodi che allochi uno per uno.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  7. #7
    Ok, allora mi serve sapere solo le ultime due cose. Come va implementato nella linkedlist il distruttore? Io inzialmente:

    codice:
    ~LinkedList(){
    delete element;
    delete next;
    }
    Ma in realtą non li ho dichiarati come puntatori nella classe, ma come oggetti di tipo Node....come andrebbe fatto?
    Per finire, quando si fa la delete dei puntatori cosa succede concretamente? Viene deallocata la memoria? Cioč se non sbaglio un puntatore č una locazione di memoria dove ho un puntatore ad un' altra locazione di memoria, quindi in quel modo rimuovo il puntatore, cioč libero quell' area di memoria?

  8. #8
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Nella LinkedList hai due Node* : header e trailer e sono questi due che vanno cancellati.
    Essendo una lista non č sufficiente cancellarne solo uno, ma č necessario scorrere tutta la lista e cancellare i vari nodi uno per uno. Vale sia per header sia per trailer.
    Supponendo ( e spero sia cosģ) che l'ultimo puntatore next della classe Node sia NULL, la procedura č questa:
    codice:
    LinkedList::~LinkedList() {
    
        Node* tmp = NULL;
    
        while ( header != NULL) {
            tmp = header;
            header = header->getNext();
            delete tmp;
        }
    
        while ( trailer != NULL) {
            tmp = trailer ;
            trailer = trailer ->getNext();
            delete tmp;
        }
    }
    Il distruttore della classe Node - teoricamente - dovrebbe distruggere il puntatore a Film. Il problema č che non si sa chi possiede tale puntatore, vale a dire che non si sa se l'eventuale cancellazione spetta al distruttore di Node oppure al chiamante. E questo perché il metodo getElement() della classe Node restituisce la stessa zona puntata da element.
    Inoltre i metodi di LinkedList restituiscono a loro volta il puntatore a element della classe Node e un vector<Film*> che contiene i vari puntatori ai vari element della class Node.
    Prima o poi andrai a cancellare tali puntatori e qui sono dolori. Una doppia delete su un puntatore si paga cara in C++. Hai due tiratori e un unico piattello: solo uno colpisce il piattello, l'altro impallina la quaglia che ci passa dietro. In definitiva devi decidere chi possiede il diritto esclusivo di colpire sto piattello/cancellare il puntatore.
    Oppure se vuoi evitare tutte ste paranoie, usare std::shared_ptr<Film> al posto di Film*
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  9. #9
    Perchč fai in quel modo la delete della linkedList?

    codice:
     Node* tmp = NULL;
    
        while ( header != NULL) {
            tmp = header;
            header = header->getNext();
            delete tmp;
        }
    Gią in questo modo dopo aver superato trailer arrivo a NULL e ho cancellato la lista, perchč fai il ciclo sul trailer? Ma quindi devo fare la delete anche per i vector?
    Stavo pensando...se nei cpp creo dei metodi in cui uso i puntatori devo rimuovere anche quelli? Tipo in un metodo di tipo:

    codice:
    Node* LinkedList::isPresent(Film* f)
       {
           if(getSize()>0)
           {
               for(Node *tmp=header->getNext(); tmp!=trailer; tmp=tmp->getNext()){
                   if(tmp->getElement()->getTitolo()==f->getTitolo() /*&&
                           tmp->getElement()->getRegista()==f->getRegista()*/)
                       return tmp;
               }
           }
           
           return NULL;
       }
    E tipo se nel main ho un sacco di switch del tipo:

    codice:
    case 8:
                         {  
                           cin.clear(); 
                           cin.ignore(2, '\n'); 
                           vector<Film*> vett=distr->ListaRemake();
                           vector<Film*> ::iterator it;
                                                   
                           
                           if(vett.size()!=0){
                              for(it=vett.begin(); it!=vett.end(); it++){
                                 Film* current=*it;
                              cout<< current->toString();
                              }
                           }
                           
                           else cout <<"Non sono presenti remake."<<endl;
                        break;  
                         }
    Devo fare la delete pure di tutti questi puntatori? Che confusione.....

    Del resto, se volessi fare il distruttore di film, che non ha puntatori, come faccio?

    codice:
    #include "Film.hpp"
    
    Film:: Film(string title, string reg)
    {
        titolo=title;
        regista=reg;
        isRemake=false;
        annoUscita=-1;
        
    }
    
    Film::Film(string title)
    {
        titolo=title;
    }
    
    Film:: ~Film(){ 
        
    }
    
               void Film::setisRemake(bool value){isRemake=value;}
               void Film::setTitolo(string value){titolo=value;} 
               void Film:: setRegista(string name){regista=name;}
               void Film:: setOriginale(string film){originale=film;}
               void Film:: setAttori(string actors){attori.push_back(actors);}
               void Film:: setAnnoUscita(int anno){annoUscita=anno;}
               void Film:: setCopieTotali(int copie){copieTotali=copie;}
               void Film:: setCopiePresenti(int copie){copiePresenti=copie;}
               string Film:: getTitolo(){return titolo;}
               string Film:: getRegista(){return regista;}
               string Film ::getOriginale(){return originale;}
               vector<string> Film:: getAttori(){return attori;}
               int Film:: getAnnoUscita(){return annoUscita;}
               int Film:: getCopieTotali(){return copieTotali;}
               int Film:: getCopiePresenti(){return copiePresenti;}
               
              /* void Film::FissaOriginale(Film* remake, Film* original){
                   if(original->getAnnoUscita()<=remake->getAnnoUscita())
                   {
                      remake->setOriginale(original->getTitolo());
                      remake->setisRemake(true);
                   }
               }*/
               
               void Film::FissaOriginale(Film* remake, Film* original){
                   if(original->getAnnoUscita()<=remake->getAnnoUscita())
                   {
                      remake->setOriginale(original->getTitolo());
                      remake->setisRemake(true);
                   }
               }
               
               string Film::toString(){
                   
                  string toReturn;
                  stringstream out;
                 
                   Film* f=this;
                   out << f->getAnnoUscita();
                   toReturn+='('+f->getTitolo()+", "+f->getRegista()+", "+out.str()+")";
                   return toReturn;
               }

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.