Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177

    [C++] Costruttore di copia

    Mi sono trovato per la prima volta a dover implementare un costruttore di copia, dato che la classe per cui lo devo fare è simile a quella che qui riporto

    codice:
    class Prova
    {
      public:
        
        //metodi che servono
        //...
        
        //costruttore di copia
        Prova(const Prova& da_copiare);
        
      private:
        
        //altri dati membro
        //...
        
        //membro di tipo puntatore
        TipoPuntatore* mPuntatore;
        
    };
    Ora, io l'ho implementato in questo modo, ma chiedo se si può fare in un modo migliore, in quanto mi sembra piuttosto macchinoso il sistema, ma non ho trovato altra strada.

    Con qualche riga di codice, ecco cosa ho fatto

    codice:
    Prova::Prova(const Prova& da_copiare)
    {
      //1) copio in un puntatore temporaneo il puntatore dell'oggetto da_copiare
      TipoPuntatore* puntatore_temporaneo=da_copiare.mPuntatore;
      //2) ricavo i dati puntati dal puntatore dato membro dell'oggetto che deve essere copiato
      TipoDatiDaCopiare dati_temporanei=puntatore_temporaneo->getDati();
      //3) creo l'istanza del dato membro puntatore del nuovo oggetto partendo dai dati ricavati mediante il puntatore temporaneo
      mPuntatore=new TipoPuntatore(TipoDatiDaCopiare dati_temporanei);
    }
    Grazie

  2. #2
    Utente di HTML.it L'avatar di boots
    Registrato dal
    Oct 2012
    Messaggi
    1,626
    Ma non ti conviene definire un costruttore di copia anche per TipoPuntatore ?
    così poi nel costruttore di copia di Prova basta che fai

    codice:
    Prova::Prova(const Prova& da_copiare){
       mPuntatore = new TipoPuntatore(*da_copiare.mPuntatore);
    }

  3. #3
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    TipoPuntatore è una classe astratta da cui derivo una famiglia di classi (Tipo1,Tipo2,Tipo3, ecc i cui dati membro sono solo alcuni double, per cui potrebbe andare bene quello che fa il compilatore per la copia).

    quindi in realtà dovrei correggere quanto ho scritto circa l'implementazione del costruttore di copia

    codice:
    Prova::Prova(const Prova& da_copiare)
    {
      //1) copio in un puntatore temporaneo il puntatore dell'oggetto da_copiare
      TipoPuntatore* puntatore_temporaneo=da_copiare.mPuntatore;
      //2) ricavo i dati puntati dal puntatore dato membro dell'oggetto che deve essere copiato
      TipoDatiDaCopiare dati_temporanei=puntatore_temporaneo->getDati();
      //3) ricavo il tipo di classe istanziata in Prova
      TipoPuntatore::Type temp_type=puntatore_temporaneo->getType();
      //4) creo l'istanza del dato membro puntatore del nuovo oggetto partendo dai dati ricavati mediante il puntatore temporaneo
      mPuntatore=Factory::makeTipoPuntatore(TipoDatiDaCopiare dati_temporanei, TipoPuntatore::Type temp_type);
    }
    Spero di essermi spiegato...

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Per evitare tutto questo giro di codice è sufficiente implementare il pattern prototype.
    In questo modo puoi fare semplicemente:
    codice:
    class TipoPuntatore {
        public:
            ...
            virtual TipoPuntatore* clone()=0;
            ...
    };
    
    class Concreta : public TipoPuntatore {
         double d;
         public:
         TipoPuntatore* clone() {
              Concreta* temp = new Concreta;
              temp->d = this->d;
              return temp;
         }
    
    };
    ...
    Prova::Prova(const Prova& da_copiare) {
        mPuntatore = da_copiare.mPuntatore->clone();
    }
    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
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Quote Originariamente inviata da shodan Visualizza il messaggio
    Per evitare tutto questo giro di codice è sufficiente implementare il pattern prototype.
    Mai avrei pensato di usarlo a questo scopo, o meglio, il problema del costruttore di copia mi ha offuscato la vista sul problema.

    Infatti mi dicevo, ma io devo copiare un dato membro, non un oggetto...ma in realtà il dato membro è un oggetto di cui esiste un'istanza nel momento in cui lo voglio copiare, quindi ben venga il Prototype (che sono andato a rileggermi in quanto non lo avevo mai usato fino ad ora).

    Grazie infinite nuovamente

  6. #6
    Utente di HTML.it L'avatar di ing82
    Registrato dal
    Sep 2014
    Messaggi
    177
    Quote Originariamente inviata da shodan Visualizza il messaggio
    codice:
    Prova::Prova(const Prova& da_copiare) {
        mPuntatore = da_copiare.mPuntatore->clone();
    }
    Una cosa simile l'ho sfruttata anche per fare l'overload dell'operatore=,

    codice:
    void Prova::operator=(const Prova& da_copiare)
    {
      mPuntatore=da_copiare.mPuntatore->clone();
    }
    Però facendo così rischio quasi sicuramente un memory leak: o faccio delete prima di assegnare il nuovo 'valore' a mPuntatore o passo agli smartpointer, credo in questo caso unique_ptr per mPuntatore.

    Con l'operatore di copia non ho questo rischio in quanto sto creando l'oggetto, ho capito giusto?
    Ultima modifica di ing82; 04-06-2016 a 18:36

  7. #7
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Se non intendi usare unique_ptr puoi scrivere:
    codice:
    Prova& Prova::operator=(const Prova& da_copiare) {
        TipoPuntatore* temp = da_copiare.mPuntatore->clone();
        delete mPuntatore;
        mPuntatore = temp;
        return *this;
    }
    In questo caso se la prima riga lancia un'eccezione, mPuntatore di Prova è preservato. Viceversa se prima fai il delete di mPuntatore e poi fai la copia, perdi tutto.
    In casi simili, si usa un puntatore temporaneo e poi se tutto va bene si procede a cancellazione e copia, altrimenti si perdono capra e cavoli.
    Con l'operatore di copia non ho questo rischio in quanto sto creando l'oggetto, ho capito giusto?
    Esatto.
    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.

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 © 2025 vBulletin Solutions, Inc. All rights reserved.