Newsgroup: it.comp.lang.c++
Titolo: su dati privati e overloading

Ciao a tutti,
sono nuovo sia del newsgroup che della programmazione C++, innanzitutto un
saluto a tutti, vengo subito al punto che mi affligge per non farvi perdere
tempo.
supponiamo di avere la classe seguente:
class prova {
 private:
  int i,j;
 public:
      prova(int ii,int jj) {
           i=ii;
           j=jj;
  }
      void setProva(int,int);
      void print();
      prova operator+(prova);
};
e che ridefinisca l'operatore + in questo modo:
prova prova::operator+(prova p)  {
     return prova(i+p.i,j+p.j);
}
il tutto mi funziona perfettamente, quello che non capisco č perche non
riceva un errore quando nella ridefinizione di + accedo alle variabili
PRIVATE  p.i   p.j
alle quali normalmente non posso accedere.
spero mi sappiate rispondere, grazie
Paolo

 alle quali normalmente non posso accedere.
I membri interni di una classe possono accedere alle variabili private.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it

 > il tutto mi funziona perfettamente, quello che non capisco č perche non


prova(const int ii, const int jj) : i(ii), j(jj) {}
Che senso ha qui il const?
-- 
Marco Barisione (ICQ 84277092)

 alle quali normalmente non posso accedere.
spero d'aver capito...
penso tu ti riferisca al fatto che operator+ agisce sulla parte private di
una istanza di prova (p) non "sua", nel senso che e' diversa dall'istanza
che contiene il metodo che stai chiamndo (*this).
se e' questo il tuo dubbio...
questo e' legittimo poiche' in C++ la protezione d'accesso alle variabili
(private, public, protected)
e' a livello di classe e non di istanza;
in soldoni:
un metodo qualsiasi di una istanza di prova puo' liberamente accedere ad
*ogni* variabile (private, public, protected) di *ogni* altra istanza di
prova, senza problemi...
--
Ciao by Allanon

era esattamente quello che non capivo, pensavo che ogni metodo potesse
accedere solamente alle variabili private dell'istanza che chiama quel
metodo e non alle variabili di qualunque istanza di quella stessa classe
grazie


 prova & prova::operator + (const prova & p);
č semplicemente per rendere il codice piů robusto?
o ci sono giustificazioni piů profonde
Paolo

 Che senso ha qui il const?
In effetti nessuno. Questa dichiarazione e' del tutto equivalente a 
prova(int ii, int jj);
Ciao,
Nicola

 prova & prova::operator + (const prova & p);
perche' restituisci un riferimento? Non sarebbe meglio restituire per 
valore?
ciao Anto
-- 
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 o ci sono giustificazioni piů profonde
qui e' corretto mettere const in quanto cosi' puoi scrivere:
const prova p1;
prova p2(p1);
se non c'era const non potevi farlo...
e potevi costruire p2 solo a partire da oggetti non-const.
--
Ciao by Allanon

 e potevi costruire p2 solo a partire da oggetti non-const.
ehm, ovviamente non ho attaccto il cervello prima di rispondere...
pensavo fosse il costruttore per copia...
cmq il discorso e' analogo.
se gli metti "const" puoi fare (spero sta volta sia giusto!)
const prova p1;
prova p2;
p2=p2+p1;
chiama operator+ di p2 passandogli com parametro p1 (riferimento a...).
se non avessi definito operator+ con const non avresti potuto farlo...
e avresti potuto chiamare op+ solo con
prova p1;//p1 e' non const.
Ovviamente nel codice di operator+ non puoi modificare l'argomento passato
come const.
se ci provi ottieni un errore a compile-time.
spero di aver collegato il cervello e di essere stato chiaro :-)
--
Ciao by Allanon

metodo e non alle variabili di qualunque istanza di quella stessa classe
Non avrebbe senso, le variabili sono private perché non si possano
usare dall'esterno ma si presume che chi scrive una classe sia in
grado di non fare pasticci (come potrebbe invece fare un utilizzatore
esterno) e quindi di poter accedere senza problemi anche a dati
privati.


se ho capito bene mi stai dicendo che uso un argomento const per poter poi
usare variabili sia const che non quando utilizzo l'operatore +?


 usare variabili sia const che non quando utilizzo l'operatore +?
si, proprio cosi'.
ed il discorso e' generale, vale ovviamente per ogni metodo
(da qui in poi prendi con le pinze quello che dico, magari in attesa dei
piu' esperti... :-) )
se in un metodo non modifichi l'argomento passato *per riferimento* e' uso
metterci const cosi' "allarghi" il campo di applicabilita' del metodo
stesso.
lo specificatore const non serve se invece passi l'argomento "per valore"
(ossia mediante la copia dell'argomento).
per i tipi built-in tra l'altro e' sempre cosi', quindi, come hanno gia'
detto:
metodo(const int a) equivale a metodo(int a)
stessa cosa per le classi, solo che passare per valore e' un bello
spreco...poi dipende dai casi.
ed ovviamente deve essere presente il copy cstr della classe da passare per
valore.
cmq penso che la cosa migliore sia che tu faccia un bel po' di prove con
tutti i casi possibili...
ci metti pochissimo e capisci al volo tutto!
spero di non aver detto troppe ca**ate! :-P
--
Ciao by Allanon

 prova & prova::operator + (const prova & p);
Questo no. Ti confondi con operator+=. Io la dichiarerei:
prova prova::operator+ (const prova & p) const;
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

 --
Io ancora meglio la dichiarerei:
const prova prova::operator+(const prova & p) const;
cosi' puoi evitare di far scrivere cose bruttissime del tipo:
a + b = c;
o sbaglio ?
-- 
Posted from 
dell-01.mm.eutelsat.org
 [194.214.173.17] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 funzione) al contrario di quanto detto da Nicola.
Nel caso specifico le due cose *sono* equivalenti, perche' entrambe le
definizioni si riferiscono ad un costruttore dichiarato:
prova(int, int);
Anche l'effetto e' identico perche' i valori sono sempre copiati. Nel
caso piu' generale non trovo che sia particolarmente utile specificare
const per un parametro passato per valore; non e' comunque diverso dallo
specificare const una variabile locale alla funzione (ovvero l'utilita'
varia caso per caso).
Ciao,
Nicola

 o sbaglio ?
Un conto e' usare il compiltore per evitare errori involontari. Un conto e'
pretendere che eviti le cretinate.
Si potrebbe anche cercare di impedire cose come
*((C*)(&(a+b)))=c;
facendo l'overload di "operator&() const" e facendogli tornare una classe che
mantiene buona parte della semantica di un puntatore a C costante ma che non e'
convertibile a C*.
Ma non ha alcun senso. L'oggetto ritornato da operator+ e' di proprietą del
chiamante, e sta a lui gestirlo come gli pare.


 chiamante, e sta a lui gestirlo come gli pare.
Siamo in democrazia quindi e' vero.
Ma non sono della stessa opinione. La mia filosofia e' questa:
    "Se scrivi un operatore scrivilo in maniera tale che faccia quello che
l'utente si aspetta"
Andando ad un estremo: Se scrivo loperatore+ e' chiaro che voglio
implementare l'operatore
+ (almeno) e non che voglio spedire una email minatoria al capo!!!!
A proposito, era da tanto che volevo dirtelo, sei proprio un ganzo ad avere
quei bei punteggi su Brainbench!!!!


 quei bei punteggi su Brainbench!!!!
Sono punteggi patetici. Feci il test per vedere come funzionava BB. E lo feci
dopo 3 anni senza aver visto un compilatore. E non intendo rifarlo proprio per
non dare spazio a discorsi come il tuo. Lo sanno tutti in questo NG. Tranne te.


 Comunque non sono "errori". Se ti va fallo pure.
Mi spieghi perche' affermi che il const appesantisce il codice ?
Un const non appesantisce per nulla il codice e secondo me lo rende +
leggibile,
quando vedi dichiarata una variabile const sai gia che non verra' mai
modificata.


 modificata.
Dipende. Se vedo const non penso che la variabile non va modificata, penso che
esiste un valido motivo per cui modificarla viola l'astrazione che la variabile
implementa e PERTANTO non va modificata. Se questo motivo non mi e'
immediatamente evidente, perdo tempo a cercare qual'e' (e ad aggiungerlo alla
documentazione perche' il prossimo che legge il codice non debba fare
altrettanto).


 altrettanto).
Appunto "Dipende". Io personalmente quando ispezziono codice scritto da
altri
"rompo le palle" e voglio il const in "ogni dove" (se possibile ovviamente),
e ti diro'
alcune volte preferisco un "metodo const + una variabile mutable" che un
metodo
che non sia const. Un esempio?
se ho un metodo del tipo:    getQualcheCosa() voglio che sia const,
altrimenti o gli cambi nome o lo fai const, poi se la getQualcheCosa()
all'interno modifica che so: "le statistiche di uso" allora che queste
statistiche
siano mutable.
Spero di essere stato chiaro.
Comunque e' solo questione di stile.
--
Gaetano Mendola.


 siano mutable.
Su questo esempio sono perfettamente d'accordo con te. A meno che le statistiche
suddette non facciano parte dell'astrazione stessa della classe (nel qual caso
il metodo sarebbe getSomethingAndUpdateStats).


 il metodo sarebbe getSomethingAndUpdateStats).
Hai colpito nel segno.


 valore al "limite" poi puoi toglierlo.
Ma quello che io ho detto e' non non andrebbe proprio messo (tanto meno
pubblicato). E il motivo e' che quel const potrebbe essere necessario toglierlo
in una implementazione successiva. E dover modificare un header pubblico per
permettere una diversa implementazione del codice in un file .cpp che pubblico
non e' e' una pessima cosa. Soprattutto se la modifica dell'header obbliga a
dover ricompilare codice senza che questo non subisca alcuna influenza.
Supponi di avere un header con la dichiarazione:
float foo( const int i );
e di doverlo modificare in
float foo( int i );
Questa modifica obbliga la ricompilazione di tutto il codice che include
quell'header. Immagina un sistema di dimensioni medio-grandi. Questa
ricompilazione potrebbe richiedere qualche ora-macchina e obbligare a rieseguire
tutti i test relativi a tutto il codice ricompilato (magari anche 2 o 3
settimane di lavoro per una decina di persone). Test teoricamente inutili
perche' la signaturte della funzione non e' cambiata e il funzionamento della
foo di per se potrebbe essere identico (basta testare la nuova implementazione
della foo stessa, senza ritestare anche tutti coloro che la chiamano). Pero' non
e' possibile saltare i test perche' le procedure di controllo qualità prevedono
che se un modulo viene ricompilato deve poi essere anche ri-testato. Non importa
se il programmatore e' sicuro a priori che non e' cambiato nulla.
E perche' poi. Solo perche' la nuova implementazione, per un motivo che non ci
interessa dato che non siamo noi a modificare o scrivere il codice della foo, ha
bisogno di trattare il parametro come non costante. Cosa che non ha alcun
effetto su di noi.
Quindi la cosa vale al contrario. La dichiarazione dovrebbe essere
float foo( int i );
fin dall'inizio sia per gli utenti che per lo sviluppatore di foo.
Se poi lo sviluppatore di foo non ha bisogno di modificare quel parametro, non
lo faccia. Il fatto che sia o meno costante non cambia l'astrazione che
rappresenta (e' un valore intero deciso dal chiamante, che stia in una variabile
o in una costante al chiamante non frega assolutamente nulla).


 io l'ho imparata da lui).
per la cronoca, anche Sutter la consiglia.
ciao anto
