Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Chiarimenti concetto e utilizzo *this (discussione)
Forum - C/C++ - Chiarimenti concetto e utilizzo *this (discussione)

Avatar
LucaLuca (Normal User)
Newbie


Messaggi: 15
Iscritto: 25/06/2011

Segnala al moderatore
Postato alle 18:07
Sabato, 25/06/2011
Apro una nuova discussione...essendo nuovo del forum non sapevo della differenza tra domanda e discussione e dell'impossibilità di rispondere solo attraverso commenti delle domande. Dovendo porre ulteriori domande e inserire anche del codice mi era impossibile continuare nel precedente post.

Quoto:

Salve a tutti,
sto leggendo il libro "C++ Fondamenti di programmazione" di Deitel. Un paragrafo porta in esame il puntatore this. Premesso che quanto letto prima l'ho appreso chiaramente (per intenderci, il concetto di puntatore mi è chiaro) vorrei chiedervi alcune delucidazioni a riguardo.

I miei dubbi sono innanzitutto concettuali. Vi riporto parte del testo

"Ogni oggetto può accedere al proprio indirizzo tramite un puntatore di nome this. [...] Il puntatore this viene usato implicitamente per riferire sia i dati che le funzioni membro di un oggetto, e può essere anche utilizzato esplicitamente"

In particolare l'ultima parte non mi è chiara. Vi chiedo gentilmente di spiegarmi questo puntatore o in alternativa di postare link a guide online.

Grazie milleee

P.S. Ho già cercato su google ma non ho trovato nulla di soddisfacente


Edit: Naturalmente anche guide in lingua inglese, non necessariamente italiano


RISPOSTA PieroTofy:

Quando fai riferimento ad una variabile membro oppure ad un metodo dall'interno della classe che lo contiene:

Codice sorgente - presumibilmente C++

  1. class A{
  2.       private:
  3.       int i;
  4.      
  5.       void f1(){
  6.          i = 0;  // <-- esempio
  7.       }
  8.      
  9.       void f2(){
  10.         f1(); // <--- esempio
  11.       }
  12.     };



Durante la fase di parsing il compilatore riconoscerà che i membri fanno parte della stessa classe e aggiungerà:

Codice sorgente - presumibilmente C/C++

  1. void f1(){
  2.       (*this).i = 0;
  3.     }
  4.     void f2(){
  5.       (*this).f1();
  6.     }



Ovviamente i (*this) sono impliciti e sarebbe ridondanti scriverli, quindi il compilatore si fa carico di inserirli al posto tuo. Ma se vuoi scriverli esplicitamente te stesso (come nel secondo pezzo di codice), puoi farlo.

Ultima modifica effettuata da LucaLuca il 25/06/2011 alle 18:10
PM Quote
Avatar
LucaLuca (Normal User)
Newbie


Messaggi: 15
Iscritto: 25/06/2011

Segnala al moderatore
Postato alle 18:23
Sabato, 25/06/2011
Fin qui tutto chiaro...

posto ora parte di un programma esempio che sfrutta il puntatore this per effettuare chiamate a cascata attraverso l'operatore .

DEFINIZIONE CLASSE TIME
Codice sorgente - presumibilmente C++

  1. #include "Time.h"
  2.  
  3. Time::Time (int hr, int min, int sec)
  4. {
  5. setTime (hr,min,sec);
  6. }
  7.  
  8. Time &Time::setTime(int h, int m, int s)
  9. {
  10. setHour(h);
  11. setMinute(m);
  12. setSecond(s);
  13.  
  14. return *this;
  15. }
  16.  
  17.  
  18. Time &Time::setHour(int h)
  19. {
  20. CODICE DI VERIFICA ORA
  21.  
  22. return *this;
  23. }
  24.  
  25. Time &Time::setMinute(int m)
  26. {
  27. CODICE DI VERIFICA MINUTO
  28.  
  29. return *this;
  30. }
  31.  
  32. Time &Time::setSecond(int s)
  33. {
  34. CODICE DI VERIFICA SECONDO
  35.  
  36. return *this;
  37. }



MAIN PROGRAM
Codice sorgente - presumibilmente C/C++

  1. #include "Time.h"
  2. int main()
  3. {
  4. Time t;
  5.  
  6. t.setHour(18).setMinute(20).setSecond(29);
  7.  
  8. }




(se necessario posterò anche il prototipo della classe. Si noti che le variabile hour, minute, second sono dichiarate come interi privati all'interno della classe.)


t.setHour(18).setMinute(20).setSecond(29);

Questa espressione mi è chiara: restituendo le tre funzioni un riferimento all'oggetto è come se scrivessi:
t.setHour(18)  => t.setMinute(20) => ecc..

e quindi ottengo la chiamata a cascata come voluto.


Non capisco in realtà la funzione setTime. Una volta che la funzione a chiamato setHour quest'ultima restituisce un riferimento ad un oggetto. Non dovrebbe restituire 0 in uscita? Perchè si deve resitutire un riferimento all'oggetto? Come viene gestito dal compilatore?

Grazie mille!

PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 414
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 19:40
Sabato, 25/06/2011
Codice sorgente - presumibilmente C/C++

  1. Time &Time::setTime(int h, int m, int s)
  2. {
  3. setHour(h);
  4. setMinute(m);
  5. setSecond(s);
  6.  
  7. return *this;
  8. }



In questo caso, il risultato di setHour, setMinute e setSecond non viene usato. Non so precisamente come lo gestisca il compilatore, ma penso che invece di salvare il risultato come sarebbe facendo Time& t = setHour(h); lo scarti
Comunque il metodo in questo caso è riscrivibile così:
Codice sorgente - presumibilmente C/C++

  1. return setHour(h).setMinute(m).setSecond(s);


In effetti il ritornare un reference da setTime() non pare molto intelligente, però ipotizznado che ci siano altri metodi nella classe potrebbe essere utile per fare
Codice sorgente - presumibilmente Plain Text

  1. t.setTime(...).altro_metodo();


Ultima modifica effettuata da lumo il 25/06/2011 alle 19:43
PM Quote
Avatar
LucaLuca (Normal User)
Newbie


Messaggi: 15
Iscritto: 25/06/2011

Segnala al moderatore
Postato alle 0:20
Domenica, 26/06/2011
Codice sorgente - presumibilmente C/C++

  1. return setHour(h).setMinute(m).setSecond(s);



Non ho capito...tu intendi dire che la funzione setTime sia riducibile a questo codice?

In realtà il mio dubbio maggiore è proprio sul tipo di ritorno...


Codice sorgente - presumibilmente Plain Text

  1. Time &Time::setHour(int h)



Restituisce un oggetto Time in uscita...ma qual è il senso di una referenza &Time?

Se io avessi avuto funzioni set del tipo

Codice sorgente - presumibilmente C/C++

  1. int Time::setHour(int h)



utilizzate all'interno della funzione come nel codice postato avrei messaggio di errore visto che il risultato di uscita della funzione non viene coinvolto in nessuna operazione?

Ultima modifica effettuata da LucaLuca il 26/06/2011 alle 0:22
PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 414
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 10:49
Domenica, 26/06/2011
Postato originariamente da LucaLuca:

Codice sorgente - presumibilmente C/C++

  1. return setHour(h).setMinute(m).setSecond(s);



Non ho capito...tu intendi dire che la funzione setTime sia riducibile a questo codice?

In realtà il mio dubbio maggiore è proprio sul tipo di ritorno...


Codice sorgente - presumibilmente Plain Text

  1. Time &Time::setHour(int h)



Restituisce un oggetto Time in uscita...ma qual è il senso di una referenza &Time?

setHour() è dichiarata appunto con tipo di ritorno Time& per permettere le chiamate a cascate.

Se io avessi avuto funzioni set del tipo

Codice sorgente - presumibilmente C/C++

  1. int Time::setHour(int h)



utilizzate all'interno della funzione come nel codice postato avrei messaggio di errore visto che il risultato di uscita della funzione non viene coinvolto in nessuna operazione?

Eh no. E' perfettamente lecito chiamare una funzione e non usarne il valore di ritorno; lo fai anche tu nel codice che hai postato:

t.setHour(18).setMinute(20).setSecond(29);

Questa espressione mi è chiara: restituendo le tre funzioni un riferimento all'oggetto è come se scrivessi:
t.setHour(18)  => t.setMinute(20) => ecc..

infatti l'ultimo metodo che chiami, setSecond(), ritorna anche un reference a *this che per tu non usi.
Un altro esempio migliore, se ti è mai capitato di usarla, è la funzione printf()
Di solito la trovi così:
Codice sorgente - presumibilmente Plain Text

  1. printf("ciao");


Ma in realtà il prototipo di printf è int printf ( const char * format, ... );

Ultima modifica effettuata da lumo il 26/06/2011 alle 10:54
PM Quote
Avatar
LucaLuca (Normal User)
Newbie


Messaggi: 15
Iscritto: 25/06/2011

Segnala al moderatore
Postato alle 13:28
Domenica, 26/06/2011
Capito..i dubbi si riducono :k:

Ultima domanda e dopo ho capito vita morte e miracoli del this :rotfl:...

Nelle funzioni utilizzate mantengo lo schema

Time &Time::nomeFunzione (parametri)

Perchè si utilizza &Time anzichè Time nella definizione delle funzioni?

PM Quote
Avatar
lumo (Member)
Expert


Messaggi: 414
Iscritto: 18/04/2010

Segnala al moderatore
Postato alle 1:14
Martedì, 28/06/2011
Testo quotato

Postato originariamente da LucaLuca:

Capito..i dubbi si riducono :k:

Ultima domanda e dopo ho capito vita morte e miracoli del this :rotfl:...

Nelle funzioni utilizzate mantengo lo schema

Time &Time::nomeFunzione (parametri)

Perchè si utilizza &Time anzichè Time nella definizione delle funzioni?


in quella definizione & non riguarda la parte che viene dopo( Time:: ), bensì riguarda al tipo di ritorno:
Time &Time::nomeFunzione( parametri );
significa che il tipo del valore di ritorno è Time&, cioè un reference ad un'istanza di Time. Il fatto che l'& sia attaccato a nome del metodo è solo una questione di (non) stile.

Ovviamente il reference è necessario affinchè venga modificato l'oggetto su cui si chiama la funzione "a cascata" e non l'oggetto copiato.

PM Quote