Newsgroup: it.comp.lang.c++
Titolo: Overload di funzioni membro con const?

Leggendo lo Stroustrup ho notato che spesso e volentieri applica una
tecnica di questo tipo:
class A {
  int m;
public:
  int GetInt() { return m; }
  int GetInt() const { return m; }
};
alcune domande:
1) perchè funziona? Le due funzioni hanno nome e parametri
coincidenti: significa forse che la constness è una caratteristica in
base alla quale si può fare l'overload?
2) a cosa può servire una cosa del genere? Perchè non inserire solo la
versione const? Sarebbe più facile da mantenere.
3) Se io ho una istanza non-const, come faccio a richiamare la
versione const (operazione lecita), nel caso le due funzioni
eseguissero operazioni differenti? L'unico modo che ho trovato è stato
quello di creare un riferimento const e usare quello, ma non è il
massimo dell'eleganza.
Anto
--
Antonio Cuni, 18 anni, studente
Brainbench Certification: 
Master C++: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
http://www.brainbench.com/transcript.jsp?pid=1301688

 massimo dell'eleganza.
O come hai fatto o con un const_cast.
Ciao,
Nicola

A differenziare le chiamate per oggetti const e non const.
si, avevo intuito :-)
quello che intendevo è: perchè ridefinire due funzioni *uguali* in
tutto e per tutto, con la sola differenza della constness? Non
basterebbe quella const?


 massimo dell'eleganza.
Riferimento o cast. E' l'unica strada.
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

 vengono esempi.
Pensa a qualcosa tipo memcpy; la constness del parametro di
destinazione sarebbe una garanzia che sorgente e destinazione non si
sovrappongono.  In questo caso puoi risparmiarti un poco di fatica.
-- 
Maurizio Loreti                         
http://www.pd.infn.it/~loreti/mlo.html
Univ. of Padova, Dept. of Physics - Padova, Italy            
lor...@pd.infn.it
The instructions said to use Windows 98 or better - so I installed FreeBSD.

parametro diverso!
hai ragione! me la condoni, oppure altre frustate? (cmq, tanto per
rispondere, è this)


 basterebbe quella const?
Se sono identiche, certamente. Di solito non lo sono: quella const
ritorna puntatore o reference a const, se non addirittura un valore,
mentre quella non const ritorna puntatore o reference a non const (in
realta' anche questa e' una semplificazione).
Un esempio di applicazione abbastanza comune e' l'operatore [] per una
classe che usa tecniche di copy-on-write. La versione const non fa la
copia.
Ciao,
Nicola

> };
Snipilito

...Scusate...uno scherzo di un collega svedese!
Come avete potuto leggere il suo italiano e´ ...molto avanzato
Maurus

realta' anche questa e' una semplificazione).
era proprio perchè sullo Stroustrup ne presenta due versioni identiche
(e non solo una volta, ma in quasi tutti gli esempi) che mi era venuto
il dubbio: boh, resterò con il mio dilemma...


 sovrappongono.  In questo caso puoi risparmiarti un poco di fatica.
Non l'ho capita. Per definizione semantica la destinazione di un memcpy non puo'
essere const!
E poi io non trovavo un esempio in cui un accessor (un metodo che non prende
parametri oltre ovviamente al this e ritorna un valore o un riferimento costante
senza cambiare lo stato logico dell'oggetto di cui fa parte) possa aver bisogno
di codice implementativo differente a seconda che l'oggetto sia const o non lo
sia. Riesco a immaginare solo due casi: l'accessor non modifica lo stato
dell'oggetto, e in questo caso basta la versione con this costante, oppure
modifica lo stato dell'oggetto (ma non dal punto di vista logico, altrimenti non
e' un accessor) e in tal caso o usi delle mutable e this costante o usi una
versione con this non costante.


 copia.
Mumble. Questa e' già meglio. Ma andiamo in un mondo diverso. L'uso di
operator[] in C++ e' una di quelle cose potentissime ma che trovo alquanto
pericolosette. Personalmente lo trovo accettabile solo nelle classi in cui
implementi anche operator->, ovvero se la tua classe assume la semantica di un
puntatore. Trovo pessimo l'uso di operator[] per i container che non ti permette
di scrivere codice solido (salvo l'uso di eccezioni) come infatti avviene per
vector della STL. Nel caso dei container, ammesso che non sia accettabile usare
at come metodo, trovo appena appena accettabile implementare operator[] che
ritorna una istanza di una classe contenente i dati per accedere per altre vie
al valore voluto (una smart reference, se vuoi).


 al valore voluto (una smart reference, se vuoi).
Questo non e' chiarissimo. Il problema fondamentale e' che operator[]
ritorna per definizione un oggetto contenuto in quello su cui e'
chiamato, e questa e' una cosa pericolosa in se. L'altro problema e' che
non c'e' modo chiaro di distinguere l'uso di [] come lvalue o come
rvalue. D'altro canto il significato intuitivo delle quadre e'
irrinunciabile ed i problemi posti sono indipendenti dal nome
dell'operatore.
Non mi sono chiare invece le critiche ai contenitori STL.
Ciao,
Nicola

 mantenuta.
Proprio per questo la criticavo nell'altro thread. Ma nota che il ritornare un
constant reference ad un oggetto contenuto e' una pratica talmente diffusa da
far parte della libreria standard. In questo senso e' meglio. Non nel senso che
e' meno rischiosa.

Per gli stessi motivi di cui sopra, l'operator[] dovrebbe ritornare una copia
del valore contenuto. Il che, salvo questioni di prestazione, lo renderebbe piu'
sicuro. Pero' cosi' facendo soddisfi solo il caso rvalue. Cosa fare per il caso
lvalue? La risposta piu' sicura sarebbe quella di ritornare una smart reference.
Ma questo non e' sempre facile o possibile. Ergo il meccanismo piu' comune e'
quello di ritornare una reference all'oggetto contenuto, che abbiamo gia'
definito come pericolosa. Ma questa e' la scelta di STL (e non solo nel caso di
operator[]). Ecco quindi la mia critica. Confronta l'implementazione C++ di
operator[] con la soluzione adottata, per esempio, in Smalltalk di definire at:
e at:set: (o in C++ at(int) e atSet(int,T), per esempio).


 e at:set: (o in C++ at(int) e atSet(int,T), per esempio).
In origine Stepanov e Lee intendevano introdurre nell'STL anche
contenitori i cui iteratori restituissero oggetti proxy, ma non se ne e'
fatto niente e la libreria standard non li prevede.
Nulla vieta di inserire nei contenitori standard dei puntatori
intelligenti, risolvendo tutti i problemi.
Ciao,
Nicola

 intelligenti, risolvendo tutti i problemi.
Certo. E' il solito discorso. Su questa linea di pensiero tutte le classi
(tranne gli smart pointer) sono allocate sempre e solo dinamicamente e
manipolate tramite smart pointers. I membri, le variabili e i parametri sono
smart pointers.
Tra il tutto e il niente esistono molte vie di mezzo. E come dicevo altrove ...
il punto di pareggio dipende da caso a caso.


 il punto di pareggio dipende da caso a caso.
In C++ si, in linguaggi piu' alla moda, meno.
Ciao,
Nicola
-- 
Posted from 
mail.divalsim.it
 [194.185.113.194] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG