Newsgroup: it.comp.lang.c++
Titolo: problemi con l'overloading di operatori

Mettiamo che abbia a che fare con una classe Matrice e voglia poter compiere
un'operazione di questo tipo:
C = A * B
dove A,B,C sono oggetti di tipo Matrice. Se faccio la stessa cosa con degli
int, il compilatore si occupa di crearmi una variabile temporanea sempre di
tipo int in cui puň conservare il risultato dell'operazione, ma nel mio
caso? Se mi creo "manualmente" questa variabile all'interno di operator*()
poi non posso ritornarne l'indirizzo, dal momento che essa viene distrutta
al termine della funzione. In piů non voglio sovrascrivere nč A nč B. Esiste
un modo?
Ho anche un altro problema. Mi spiego con un altro esempio: poniamo ad
esempio che voglia scrivere la funzione "Vector operator*(Matrix, Vector)".
Questa funzione svolge un'operazione che č _commutativa_, quindi mi
toccherebba definire anche "Vector operator*(Vector, Matrix)" che sarebbe la
copia identica della precedente (head a parte). C'č un modo piů efficiente
di risolvere il problema?
Grazie in anticipo,
Francesco "SiSkO" Napolitano

 di risolvere il problema?
Hmmm... il prodotto fra un vettore e una matrice quadrata
(la "mappatura" di un vettore) non e' affatto una operazione
commutativa ma e' un normale prodotto di matrici (1,n)x(n,n)=(1,n)
oppure (n,n)x(n,1)=(n,1).
Il vettore e' cioe' considerato una matrice ad una riga e n colonne
oppure a n righe e una colonna (nei testi infatti spesso si trovano
vettori *trasposti* moltiplicati per matrici).
Tornando al C++ la risposta e' no. Se proprio hai a che fare con
una operazione commutativa fra due classi devi comunque definire
i due operatori. Al limite uno dei due che chiama l'altro:
  Matrix operator*(double k,const Matrix& m)
  {
    Matrix r;
    for(int i=0; i<4; i++)
      for(int j=0; j<4; j++)
        r(i,j)=m(i,j)*k;
    return r;
  }
  Matrix operator*(const Matrix& m,double k)
  {
    return k*m;
  }
HTH
Andrea
--
----------------------------------------------------------------
 <\___/>  Andrea        email: agriff at tin dot it
 / . . \  "6502"          irc: _6502_@EFNET#italia
(  (")  ) Griffini   homepage: 
http://www.netservers.com/~agriff
Sent via Deja.com 
http://www.deja.com/
Before you buy.


Forse intendi un metodo più comodo...
Comunque il compilatore non può sapere che operator* è commutativo,
quindi devi definirli entrambi.
Al più puoi fare:
inline Vector operator*(const Vector& v, const Matrix& m)
{
    return m * v;
}
Manlio Perillo

        }
Scusa, questa non l'ho proprio capita :-/
Che operatore stai ridefinendo, e quando viene usato ?!?
Massimo

 efficiente di risolvere il problema?
        Vector operator * ( const Matrix &a, const Vector &b ){
                // codice
        }
        inline Vector operator * ( const Vector &a, const Matrix &b ){
                return b*a;
        }
Oppure definire il costruttore
        Matrix::Matrix( const & Vector v );
e l'operatore
        Matrix operator * ( const Matrix &, const Matrix & );

 ha scritto nel messaggio
news:8v1v64$h93$1...@nslave2.tin.it...



Questo è un operatore di conversione in Matrix.
Ossia un oggetto di tipo MatrixMul può essere convertito
*implicitamente* in Matrix.
Non è che sia indispensabile (anzi, per lo più potrebbe
portare ad ambiguità, vista anche l'esistenza di
Matrix(const MatrixMul&) non explicit).
Ho inserito questo operatore perchè è presente nell'esempio
dello Stroustrup, ma credo proprio che si possa eliminare.
Manlio Perillo

 *implicitamente* in Matrix.
Ah, uno dei famosi operatori di casting implicito...
Massimo

 ricorrere a copy on write + reference-counting; pero' gia' cosi' funziona.
Potresti mica spiegarmi cosa sono di preciso queste due tecniche ?
Le ho sentite nominare parecchio...
Massimo

Massimo wrote:

Premessa: non sono un teorico, per cui non mi prendere troppo alla 
lettera....
Si tratta di effettuare la copia fisica degli oggetti solo quando 
necessario ( ovvero quando si deve modificare un'oggetto )
consideriamo il seguente caso
class   X
void f( X a )
        X       b;      
        // ...
        b=a;
        // ..
}
Supponiamo che X sia una classe "molto grande" ( una grande matrice per 
esempio del tipo 1000x1000 double, circa 8 MB). Un operazione del tipo 
"b=a" significa copiare una grande quantita' di dati. Se poi ne b ne a 
devono essere modificati e' un vero e proprio spreco.
Il trucco e' non copiare quando si incontra l' operator = ( ), ma 
semplicemente tener traccia dell'operazione ( counter reference ).
Per cui nel caso
        b=a
sia b, che a punteranno allo stesso oggetto.
Se ne b ne a vengono modificati, non c'e' problema.
Poniamo che pero' b ( o a ) ad un certo punto vengano modificati:
        b[i][j]=4.0;
Allora bisogna "separare" le due copie; questa tecnica e' chiamata copy on 
write; in pratica gli oggetti diventano una specie di puntatori; durante 
una copia ( o una inizializzazione ) viene incrementato il reference 
counter; durante la distrizione di un oggetto viene decrementato. Se un 
oggetto deve essere modificato ci sono 2 casi
- il reference counter e' pari ad uno, ed allora non ci sono problemi
- il reference counter e' > di uno ed allora si provvede a fare una copia 
dell'oggetto e a decrementare il ref. counter, e finalmente a modificare la 
copia ....
pensa solo ad una riga del tipo
matrix mul( matrix a, matrix b ){
        matrix result;
        // operazioni varie
        return result;
}
// ....
r = mul( a, b );
Ci sono almeno 3 copie che potrebbero essere evitate.
Per la cronaca questa tecnica viene utilizzata su molti O.S. quando viene 
eseguita una copia di un processo ( fork ). Praticamente quando la copia 
altera una zona di memoria in comune ne viene effettuata una copia privata 
per ogni processo e solo allora modificata ....