Newsgroup: it.comp.lang.c++
Titolo: Aiuto su operatori

Ciao a tutti,
sono abbastanza un principiante in C++, in più mi hanno 'fregato' il
manuale e non so dove andare a vedere...
Sto facendo, come prova, una classe sulle matrici. Il mio problema è il
seguente: come faccio a costruire l'operatore somma? Ho scritto una cosa
del tipo:
// Nella dichiarazione della classe CMatrice
CMatrice& operator+(CMatrice& seconda)
// Nell'implementazione
CMatrice& CMatrice::operator+ (CMatrice& seconda)
{
    CMatrice ris;
// Corpo della funzione
    return ris
}
Come mi aspettavo, mi ha dato un warning avvertendomi che sto ritornando
qualcosa che in realtà non sarà propriamente disponibile... Come faccio?
TIA,
        Flavio
--
Ing. Flavio Poletti
STS s.r.l.
Via Odoardo Beccari, 13
00154 Roma, Italia
Tel. +39 6 5755096
FAX  +39 6 57287214
company e-mail: 
sts...@tin.it
private e-mail: 
pol...@writeme.com

qualcosa che in realtà non sarà propriamente disponibile... Come faccio?
MAI tornare un reference, in situazioni del genere!  Il tuo operator+ DEVE
tornare un *oggetto* CMatrice, NON un *reference* a CMatrice.  Myers,
"Effective C++", seconda edizione (OTTIMO libro!) spiega in dettaglio i
perche` e percome.  Riassumendo, tornare un reference e` corretto in
due soli casi: (a) un "contenitore" che, opportunamente "indiciato", puo`
tornare un reference a uno degli oggetti 'contenuti'; (b) un metodo di
tipo "mutatore" puo` tornare la reference "*this", per la pura (notevole)
comodita` sintattica di permettere la concatenazione di molteplici
chiamate a mutatore in una sola espressione.  Un operator+, e` chiaro,
non rientra in questi casi.
Alex

 qualcosa che in realtà non sarà propriamente disponibile... Come faccio?
Devi restituire un oggetto "vero" e non una reference ad un oggetto
temporaneo (ris) che viene distrutto appena termina l'esecuzione della
funzione, ovvero restituisci un CMatrice e non un CMatrice&.
Ciao,
Alberto
-- 
Alberto BARSELLA
PGP fingerprint = 13 3F 22 D2 0B 0A D3 25  F1 89 FE B5 82 AD 75 2A
** Beliefs are dangerous. Beliefs allow the mind to stop functioning.
A non-functioning mind is clinically dead.  Believe in nothing... **


Stai restituendo l'indirizzo di un oggetto 'automatico' creato sullo
stack e
quindi distrutto all'uscita dalla funzione .
La versione corretta restituisce generalmente il riferimento a "*this"
,ma per
tua scelta potrebbe essere anche quello dell'oggetto passato alla
funzione .
// ad esempio :
CMatrice& CMatrice::operator+ (CMatrice& seconda)
{
    CMatrice ris;
// Corpo della funzione
    return *this ;
}
Tieni presente che pero' il corpo della funzione cambiera' il valore
dell'oggetto ,e seconda la buona norma questi e' meglio che non
succeda
.
Infatti se in seguito scriverai :
CMatrice a,b,c ;
main()
{
 a = b+c ;
questo cambiera' il valore di "b" .
Per evitare cio' la funzione va' dichiarata in questo modo :
CMatrice CMatrice::operator+ (CMatrice& seconda)
{
    CMatrice ris;
// Corpo della funzione
    return ris ;
}
In questo caso la funzione restituisce un oggetto temporaneo sullo
stack
che
non provoca alcuna conseguenza .

funzione, ovvero restituisci un CMatrice e non un CMatrice&.
Non credo che basti a risolvere il problema. L'oggetto che restituisce
deve essere allocato dinamicamente. Mi sbaglio?

deve essere allocato dinamicamente. Mi sbaglio?
Si`, ti sbagli; non c'e` nessun bisogno che l'oggetto che una
funzione restituisce sia allocato dinamicamente, anzi normalmente
e` un serio errore di stile, per una funzione, restituire oggetti
allocati dinamicamente come proprio risultato e far affidamento
sul fatto che il chiamante li liberi (Meyers, "Effective C++", 2a
edizione).
Alex
--
 ____    Alex Martelli, Bologna, Italia -- email: 
al...@magenta.com
 \SM/___                                 
http://magenta.com/~alex
  \/\bi/     You never know what is enough unless you know what
     \/          is more than enough.

>PGP public key avaiable with "finger
XYWZa...@helen.cli.di.unipi.it
<<
fingerprint: D1E7 641F 1821 74BA  1836 9B50 B37C 5FA3

Alex Martelli ha scritto nel messaggio ...
[snip]
:Si`, ti sbagli; non c'e` nessun bisogno che l'oggetto che una
:funzione restituisce sia allocato dinamicamente, anzi normalmente
:e` un serio errore di stile, per una funzione, restituire oggetti
:allocati dinamicamente come proprio risultato e far affidamento
:sul fatto che il chiamante li liberi (Meyers, "Effective C++", 2a
:edizione).
:
E' un errore di stile, ma viene applicato in soluzioni che sono
cosiderate oggettivamente valide.
Es. la Abstract Factory della GOF prevede che i prodotti da essa
creati vengano 'distrutti' dal cliente della factory stessa.
Massimo

ritornata. Spero che stavolta sia azzeccato:)
OK!  Bravissimo, stavolta ci hai proprio preso.  Unico punto
degno di nota: il compilatore ha _esplicitamente_ il permesso
(da parte dello standard) di "ottimizzare via" il copy constructor
del risultato ritornato seguito da destructor dell'oggetto che
ritorna -- puo` costruire direttamente il risultato a destinazione.
La maggior parte dei compilatori ci riesce solo in certi casi
particolari, tipo un esplicito costruttore nell'espressione del
return.
Alex

creati vengano 'distrutti' dal cliente della factory stessa.
Ah, ma nel C++ moderno (dall'FDIS -- Final Draft International
Standard, Novembre 1997, a oggi e oltre:-) una Factory che si
rispetti ritorna un auto_ptr<T>, *non* un puntatore a T (men che
meno una *reference* a T, cosa che non e` mai stata accettabile).
(Prima dell'FDIS, questa sarebbe stata una soluzione assai
discutibile, ma l'FDIS ha rifatto auto_ptr<> da capo, introducendo
la sottilissima complessita` di auto_ptr_ref<>, proprio perche`
questo idioma assai preferibile divenisse "indiscutibile").
Cosi`, _se_ il cliente vuole prendersi l'ownership dell'oggetto
ritornato lo fa (esplicitamente, ovvero costruendo un suo
auto_ptr<> e poi manipolandolo come opportuno), mentre,
se non lo fa, l'oggetto viene comunque distrutto correttamente.
Molto popolari, in C++ (e da un pezzo), sono anche gli smart
pointer che fanno "reference-counting".  Anche questo tipo di
puntatori va benissimo per tornare indicazioni del genere.  E`
anche la convenzione del Component Object Model (COM),
persino per il C dove, non essendoci "smart" alcuno, il reference
count va esplicitamente manutenuto dal cliente (AddRef e
Release) -- in questo caso e` il linguaggio che non offre
proprio alternative (quindi, oggettivamente, poco valido).
In altri linguaggi, come Java o Eiffel (e in C++ con l'addizione
di un garbage collector, scelta sempre piu` popolare), di
liberare l'oggetto si fa carico "il sistema", per cui naturalmente
non c'e` problema.
Alex

 Alex
E' sempre un piacere stimolarti, per ottenere risposte intelligenti,
esperte ed esaurienti. Personalmente ti considero alla stregua di
un on_line_web_help da cui ricavare un *mare* di info.
massimo

di un garbage collector, scelta sempre piu` popolare), di
Questo è molto interessante.  I garbage collectors per il C++ esistono
come prodotti commerciali, o ne esistono di free, almeno per uso
accademico?  Mi piacerebbe provarne.
				Ciao
					Guido
-- 
    |\      _,,,---,,_     Guido Notari (EC Joint Research Centre, Ispra site)
zz  /,`.-'`'    -.  ;-;;,_  postal:  TP 210,  JRC,  21020 Ispra (VA),  Italia
   |,4-  ) )-,_..;\ (  `'-' tel: 
+39 332 785528
    fax: 
+39 332 785813
  '---''(_/--'  `-'\_)    

accademico?  Mi piacerebbe provarne.
Sia commerciali, sia free.  Di questi ultimi, il piu` popolare
(e piu` performante) e` quello di Boehm, liberamente
scaricabile dalla rete assieme al grosso pacco di paper
che Boehm ha scritto su tutti i particolari di come si puo`
realizzare tranquillamente la garbage collection per il C
e il C++.  Supporta un paccone di diversi compilatori,
fra cui il Microsoft Visual C++ 5.  Boehm continua sempre
a migliorarlo e raffinarlo sperimentando tecniche vieppiu`
avanzate.  Praticamente tutti i compilatori Java->C che
conosco, e molti altri progetti, vi si appoggiano.
E` liberamente usabile in qualsiasi tipo di progetto, che sia
commerciale o meno, mi pare.  Comunque, fra la sua
amplissima (e approfondita) documentazione ci sono anche
le condizioni di uso e ridistribuzione.
Alex