[C++] Puntatore this e overload operatori
Considerando una situazione di questo tipo (ignorando altri eventuali metodi/attributi presenti nella classe):
Il metodo setNome, essendo interno alla classe, perché dovrebbe accedere all'attributo nome tramite puntatore this? In questo caso è come se scrivessi [inline]void setNome(string nome) {Persona.nome = nome;}[/inline], o sbaglio? Non sarebbe sufficiente scrivere [inline]void setNome(string nome1) {nome = nome1;}[/inline]?
Questo dilemma si ripercuote, prevedibilmente, anche nella comprensione della sintassi per l'overload degli operatori:
Ho provato a tradurre il codice con quanto ho "capito" fin ora: considerando un oggetto "ogg", ne viene inizializzata la variabile [inline]var[/inline] tramite costruttore. Dopodiché, l'operatore [inline]+[/inline] viene modificato in modo tale da:
class Persona { string nome; public: void setNome(string nome) {this->nome = nome;} };
Il metodo setNome, essendo interno alla classe, perché dovrebbe accedere all'attributo nome tramite puntatore this? In questo caso è come se scrivessi [inline]void setNome(string nome) {Persona.nome = nome;}[/inline], o sbaglio? Non sarebbe sufficiente scrivere [inline]void setNome(string nome1) {nome = nome1;}[/inline]?
Questo dilemma si ripercuote, prevedibilmente, anche nella comprensione della sintassi per l'overload degli operatori:
class MyClass { public: int var; MyClass() {} MyClass(int a): var(a) { } MyClass operator+(MyClass &obj) { MyClass res; res.var= this->var+obj.var; return res; } };
Ho provato a tradurre il codice con quanto ho "capito" fin ora: considerando un oggetto "ogg", ne viene inizializzata la variabile [inline]var[/inline] tramite costruttore. Dopodiché, l'operatore [inline]+[/inline] viene modificato in modo tale da:
- 1) acquisire il reference dell'oggetto alla sua destra (perché si passa il reference?);
2) creare un oggetto [inline]MyClass res[/inline];
3) assegnare alla sua variabile var ([inline]res.var[/inline]) la somma tra la variabile var di "ogg" ([inline]ogg.var[/inline]) e la variabile var dell'oggetto alla destra dell'operatore ([inline]obj.var[/inline]);
4) restituire l'oggetto [inline]res[/inline][/list:u:1kb76gz8]
Potreste farmi un'esempio dettagliato di applicazione di questo overload? Ve ne sarei molto grato, grazie
Risposte
"robe92":
In questo caso è come se scrivessi [inline]void setNome(string nome) {Persona.nome = nome;}[/inline], o sbaglio?
[inline]void setNome(string nome) {Persona.nome = nome;}[/inline] è sbagliato perché [inline]Persona[/inline] non è un oggetto ma è un tipo di dato, quindi non ha senso di parlare dei suoi attributi [è come se io ti chiedessi "di che razza è il cane?" anziché "di che razza è Lessie?"].
[inline]this[/inline] si usa per specificare che si vuole accedere a qualcosa dell'oggetto corrente. Spesso può essere omesso e si usa per migliorare la leggibilità del codice e per eliminare ambiguità del codice, come nel seguente esempio:
#include <stdio.h> class Test { public: void foo(int val) { printf("val = %d\n", val); printf("val = %d\n", this->val); } private: int val = 1; }; int main(int argc, const char *argv[]) { int val = 2; Test test; test.foo(val); return 0; }
"robe92":
1) acquisire il reference dell'oggetto alla sua destra (perché si passa il reference?);
[/list:u:sbk7uuji]
Si passa una referenza per evitare di copiare l'oggetto, che potrebbe essere molto grande, mantenendo la possibilità di usarlo come un oggetto vero, cioè accedendo ai suoi membri e metodi con il punto anziché con la freccia.
"robe92":
Potreste farmi un'esempio dettagliato di applicazione di questo overload? Ve ne sarei molto grato, grazie
Ammesso che tutti i dettagli siano messi bene, questo si può usare per scrivere, ad esempio, [inline]Persona c = a + b[/inline] dove [inline]a[/inline] e [inline]b[/inline] sono oggetti della classe [inline]Persona[/inline].
"Raptorista":
[quote="robe92"]
1) acquisire il reference dell'oggetto alla sua destra (perché si passa il reference?);
[/list:u:2qggk3gs]
Si passa una referenza per evitare di copiare l'oggetto, che potrebbe essere molto grande, mantenendo la possibilità di usarlo come un oggetto vero, cioè accedendo ai suoi membri e metodi con il punto anziché con la freccia.
[/quote]
In tal caso, considerando [inline]MyClass c = a + b[/inline], se la definizione della funzione fosse [inline]MyClass operator+(MyClass* obj)[/inline], si dovrebbe avere [inline]res.var = this->var + obj->var;[/inline], con [inline]*obj[/inline] che punta a [inline]b[/inline] ([inline]MyClass* obj = &b[/inline])?
Se venisse chiamato quel prototipo, sarebbe [inline]*obj == b[/inline]; per fare ciò però credo dovresti fare qualcosa come [inline]c = a + &b[/inline].
"Raptorista":
Se venisse chiamato quel prototipo, sarebbe [inline]*obj == b[/inline]; per fare ciò però credo dovresti fare qualcosa come [inline]c = a + &b[/inline].
Giusto, grazie!
"robe92":
Considerando una situazione di questo tipo (ignorando altri eventuali metodi/attributi presenti nella classe):
class Persona { string nome; public: void setNome(string nome) {this->nome = nome;} };
La necessità del [inline]this[/inline] in quel caso deriva dal fatto che la variabile membro [inline]nome[/inline] è nascosta dalla variabile locale [inline]nome[/inline]. Scelta che sinceramente trovo discutibile

Detto questo, devi tenere conto che le funzioni membro non sono davvero "dentro" la classe. La dimensione della classe persona è [inline]sizeof(Persona) == sizeof(string)[/inline] o qualcosa in più se ci sono funzioni virtuali (a dire il vero anche l'allineamento dei dati influisce sulla dimensione di una classe). La funzione membro setNome viene trasformata nella funzione
void ___setNome___( Persona *this, string nome );dove con [inline]___setNome___[/inline] intendo il nome univoco con cui questa funzione verrà chiamata a livello di object file (sempre che il compilatore non decida di mettere l'intera funzione inline). Quindi, il fatto di poter omettere il puntatore this è utile per il programmatore ma non modifica in alcun modo le performance (il puntatore a this c'è sempre, o per meglio dire il compilatore lo aggiunge per te).
Per concludere, il tuo professore adora scrivere il puntatore [inline]this[/inline] anche quando il linguaggio ti permette di ometterlo, ma a livello di codice prodotto dal compilatore scriverlo o no non cambia nulla. Io sinceramente non lo scrivo quasi mai, ma penso che la scelta se usarlo o meno risieda solo nella leggibilità del codice e nei gusti personali.