Newsgroup: it.comp.lang.c++
Titolo: Problemino di accesso agli elementi di una matrice

Ciao a tutti
Ho creato una classe matrice e uso l'operatore () in questo modo per
ottenere l'accesso ai singoli elementi della matrice:
double& operator() (int i,int j);
Così però resituisco una variabile per riferimemtno. Questo è molto bello
(se non essenziale) se voglio andare a modificare un elemento della matrice
però non è bello se voglio limitarmi a leggerlo...
Faccio un esempio: mi piacerebbe fare una classe derivata che implementi una
matrice a banda con banada di larghezza prefissata dimodochè che gli
elementi fuori da questa banda siano automaticamente nulli. Ovviamente non
andrei a memorizzare esplicitamente questi 0 (un primo tentativo di matrice
sparsa...) ma vorrei cmq "leggerli" nel senso che quando chiedo elemento
fuori dalla banda mi viene restituito uno 0.
Per risolvere questo inconveniente avevo visto una volta un frammento di
codice in cui veniva restituito un "const double" e accanto a questa c'era
la procedura che restituiva un "double &". Ovviamente è solo un ricordo
perchè ci ho provato e ovviamente non funziona perchè l'overload se ne va a
quel paese visto che le due funzioni differiscono solo per il valore
restituito.
Se non sapreste darmi un consiglio in merito sapreste almeno dirmi come
implementereste una matrice sparsa (giusto come idea di base).
Grazie e ciao
Antonio

 come implementereste una matrice sparsa (giusto come idea di base).
io l'ho fatto così:
http://groups.google.com/groups?hl=it&lr=&ie=UTF-8&oe=UTF-8&selm=h4e99.8
8861%24n04.2529857%
40twister2.libero.it
(occhio che  matrix<T> triangolize() è sbagliata! )
ma sicuramente trovi di meglio in giro...
--
Gerolamo

 const double& operator[] (int i) const;
è tutto bellissimo ciò che mi dici e ho provato anche a farlo. In effetti
compila tranquillamente (quindi non ci sono problemi di overload) però c'è
un ma: viene sempre chiamata cmq la prima funzione.
I miei due prototipi su tuo consiglio sono:
 TIPO& operator() (int i,int j);
 const TIPO operator() (int i,int j) const;
Ti faccio un esempio di utilizzo
matrix a(2,2);
 for (int i=0;i<a.getnr();i++)
  a(i,i)=1; //gli altri elementi sono inizializzati dal costruttore uguali a
0
 cerr<<a<<'\n';
Dove l'operator<< per la matrice è il seguente:
ostream& operator<<(ostream &str, matrix &a){
 //operazioni di output
 //stampa numero di righe e colonne
 if (a.getnr()>1)
  str<<a.getnr()<<" righe  ";
 if (a.getnc()>1)
  str<<a.getnc()<<" colonne";
 str<<'\n';
 int i,j;
 if (a.getnr()>0 && a.getnc()>0)
 {
  for (i=0;i<a.getnr();i++){
   for (j=0;j<a.getnc();j++)
    str<<" "<<a(i,j)<<"  ";
   str<<'\n';
  }
  ////////cerr<<"Indirizzo del primo elemento "<<mat<<'\n';
  return str;
 }
 return str;
}
Mi va più che bene che venga chiamata "double & operator(int i, int j)"
quando vado a scrivere gli 1 nella mia matrice. Mi va un po' meno bene che
venga richiamata ancora la stessa funzione e non "const double &
operator(int i, int j) const" quando la matrice viene stampata a schermo con
<<. Mi sai spiegare? mi sono per caso perso qualcosa?
Grazie e ciao
Antonio
ps a proposito un'altra domandina: come faccio a usare la mia operator<< per
scrivere su un file?
pps il compilatore che uso è Visual C++ 6.0 se può servire

<<. Mi sai spiegare? mi sono per caso perso qualcosa?
Il fatto di chiamare un operatore oppure l'altro non dipende
da cosa vuoi fare con il valore di ritorno (se leggerlo o
scriverlo) ma dal fatto che il reference o l'istanza che
usi per chiamare l'oggetto siano dichiarati const.
Per ottenere la chiamata dell'operatore const durante la
stampa devi utilizzare qualcosa come:
 if (a.getnr()>0 && a.getnc()>0)
 {
   const matrix& ca(a);
   for (i=0;i<ca.getnr();i++){
     for (j=0;j<ca.getnc();j++)
       str<<" "<<ca(i,j)<<"  ";
     str<<'\n';
   }
 }
Per ottenere un comportamento diverso in scrittura e
in lettura e' necessario introdurre una nuova classe
che posticipi la creazione dell'elemento al momento
della effettiva assegnazione.
HTH
Andrea

  }
ho afferrato il concetto anche se mi sembra meglio dichiarare direttamente
const matrix &a come argomento passato a operator<<. Quando dichiari const
matrix & ca(a) perchè non viene richiamato il copy constructor? per caso &
(passaggio erp riferimento) funziona in questo caso in maniera analoga a *
(cioè come un puntatore)?
Grazie e ciao
Antonio

const matrix &a come argomento passato a operator<<.
Troppo tardi. Quello che lo stream riceve non e' l'oggetto matrix,
ma l'elemento ottenuto con operator()(int,int). Se viene chiamata
la versione const oppure la versione non-const di questo operatore
e' qualcosa che dipende da come chiami questa funzione: se usando
un oggetto const, un puntatore const oppure un reference const
o se usando un oggetto non-const, un puntatore non-const o un
reference non-const. Esempio:
   matrix  a(2,2);       // Oggetto non-const
   matrix& b(a);         // Non const
   matrix* c(&a);        // Non const
   const matrix& d(a);   // Reference a const
   const matrix* e(&a);  // Puntatore a const
   const matrix  f(2,2); // Oggetto const
   //matrix& g(f);       // Non const su oggetto const: vietato!
   //matrix* h(&f);      // Non const su oggetto const: vietato!
   const matrix& i(f);   // Reference a const
   const matrix* l(&f);  // Puntatore a const
   a(1,1);     // chiama la versione non-const
   b(1,1);     // chiama la versione non-const
   (*c)(1,1);  // chiama la versione non-const
   d(1,1);     // chiama la versione const
   (*e)(1,1);  // chiama la versione const
   f(1,1);     // chiama la versione const
   i(1,1);     // chiama la versione const
   (*l)(1,1);  // chiama la versione const
HTH
Andrea

 solo per il valore restituito.
probabilmente tu hai visto qualcosa del genere:
class Matrix {
public:
    double& operator()(int x, int y);
    const double& operator()(int x, int y) const;
};
In questo caso l'overloading e` possibile perche` la constness di un 
metodo e` considerata alla stregua del tipo di un parametro (ed in 
effetti e` cosi`: il tipo del parametro implicito this passa da Matrix* 
a const Matrix*), pero` questo trucco non risolve i tuoi problemi: 
infatti la scelta del metodo da chiamare e` fatta esclusivamente in base 
alla constness della matrice su cui operi e *non* sull'utilizzo del 
reference restituito. Tanto per chiarire:
void foo(Matrix& m, const Matrix& cm)
{
     m(0,0); // chiama il metodo *non* const
     cm(0,0); // chiama il metodo cont
}
spero di esserti stato d'aiuto
ciao Anto
-- 
"Computer science is not about computers any more than astronomy
is about telescopes." -- EW Dijkstra