Newsgroup: it.comp.lang.c++
Titolo: assegnamento classi derivate

Ho una classe Q derivata da T. Se q è un'istanza di Q e T è un'istanza 
di t, quando scrivo
    q=t;
mi dice: no match for 'operator=' in 'q = t'. Però non capisco perché si 
lamenta, mi aspettavo che chiamasse operator=(T &, const T&)... visto 
che Q& può essere automaticamente convertito a T&.
Qual è l'operatore di conversione da utilizzare in questo caso?
(T &)q=t;
funziona, ma mi sembra troppo brutale!
Inoltre non mi è chiaro perché sia necessario fare esplicitamente la 
conversione. Si consideri il seguente codice:
struct T {
   int x;
};
struct Q: public T {
   int y;
   T &t() {return *this;};
};
void assign(T &t, T &tt) {
   t=tt;
}
void assign(Q &q, Q &qq) {
   q=qq;
}
main() {
   T t;
   Q q;
   q.t()=t;     // questo funziona (1)
   assign(q,t); // questo funziona (2)
   (T&)q=t;     // questo funziona (3)
   q=t;         // undefined operator=     (4)
}
Non capisco perché in (4) mi dia errore e sia necessaria la conversione 
esplicita come in (3) quando invece in (1) e (2) la conversione viene 
fatta automaticamente.
E.


Se provi a commentare la assign(T &t, T &tt) dovrebbe darti errore
anche la (2) e dovresti capire anche il perche' della (4).
Ciao

 anche la (2) e dovresti capire anche il perche' della (4).
Credo di aver capito il motivo, e mi pare non sia quello che indichi. 
Dipende dal fatto che la funzione operator= viene interpretata come 
funzione membro e che se una classe derivata definisce una funzione con 
lo stesso nome ma con "signature" diversa, per motivi di cautela, non 
viene automaticamente chiamata la funzione della classe base.
Ad esempio:
struct T {
   void test(int) {};
};
struct Q: public T {
   void test() {};
};
main() {
   Q q;
   q.test(1); // no matching function for call to `Q::test(int)'
};
Resta la domanda su quale sia il modo giusto di fare la conversione. In 
questo esempio la soluzione corretta sarebbe:
   q.T::test(1);
che però diventerebbe illeggibile nel caso di operator=:
   q.T::operator=(t);
c'è una soluzione migliore?
E.

 che Q& può essere automaticamente convertito a T&.
'T::operator=(const T&)', pur ereditato da Q, è "nascosto" dalla presenza di
'operator=(const Q&)', implicitamente definito. Per farlo "emergere" puoi
usare 'using' nella definizione di Q:
            using T::operator=;
Ciò che è spiegato in [1] vale anche per l'operatore assegnamento.
(NB: le FAQ aggiornate sono su [2], ma al momento quel sito non sta
funzionando benissimo.)
*Links*
[1] 
http://geneura.ugr.es/~jmerelo/c++-faq/strange-inheritance.html#faq-23.6
[2] 
http://www.parashift.com/c++-faq-lite/
Max


L'operatore di assegnazione, in mancanza di uno esplicito, esegue la
copia binaria dal sorgente dei dati necessari al target.
Mentre e' lecito fare:
T t;
Q q;
t = q;
in quanto 'q' contiene tutti i dati necessari per riempire 't' non è
vero il contrario.
Quindi o definisci un operatore opportuno o fai come dice Max. con
l'using.
Ciao

 conversione. Si consideri il seguente codice:
Credo di avertelo gia' spiegato sopra.
Ciao,
Nicola

 dell'operatore di assegnamento di Q.
Sě, č quello che voglio. Diciamo che questo utilizzo "strano" fa pensare 
che in effetti potrebbe essere piů sensato:
   struct Q {
     T t;
   };
invece che
   struct Q: public T {
   };
cioč che Q contiene un T, invece che Q č un T. Perň per certi versi mi č 
piů comoda la seconda interpretazione in quanto nella maggior parte dei 
casi di Q viene utilizzata solo la parte T.
Per la cronaca Q rappresenta un punto e T rappresenta un punto con 
qualche attributo (ad esempio il colore). Per spostare il punto č comodo 
utilizzare l'operazione di assegnamento. In effetti la traslazione 
tramite += funziona correttamente in quanto Q non ridefinisce 
l'operazione +=. Sarebbe quindi strano non utilizzare = per lo 
spostamento assoluto.
E.