2012-04-19 3 views
12

Quando provo a compilare il seguente (g ++ 4.6.3)Sovraccarico dell'operatore C++: nessuna conversione nota da oggetto a riferimento?

class A {}; 

A& operator*=(A& a, const A& b) 
{ 
    return a; 
} 

A operator*(const A& a, const A& b) 
{ 
    return A(a) *= b; 
} 

int main(int, char*[]) 
{ 
    A a, b; 

    a = a*b; 

    return 0; 
} 

ottengo l'errore

/tmp/test.cxx: In function ‘A operator*(const A&, const A&)’: 
/tmp/test.cxx:14:20: error: no match for ‘operator*=’ in ‘(* & a) *= b’ 
/tmp/test.cxx:14:20: note: candidate is: 
/tmp/test.cxx:6:1: note: A& operator*=(A&, const A&) 
/tmp/test.cxx:6:1: note: no known conversion for argument 1 from ‘A’ to ‘A&’ 

Questo mi lascia perplesso - come può una conversione da una classe a un riferimento a quella classe non essere conosciuto?

Modifica della dichiarazione di classe A come segue non ha alcun effetto:

class A 
{ 
public: 
    A() {} 
    A(const A&) {} 
}; 

stesso errore.

Sarei estremamente grato per suggerimenti su cosa sta succedendo qui.

+0

È possibile risolvere questo problema dichiarando l'operatore nel campo di applicazione della classe. Quindi la firma del metodo sarà simile a: 'Un operatore * (const A & rhs) const;' Se si desidera utilizzare l'operatore composto per l'implementazione, è possibile scrivere: 'return * this * = rhs' – Paranaix

+0

@Paranaix: No, non è possibile utilizzare 'operator * =' su '* this' all'interno di' const' funzione membro, poiché modificherà '* questo'. –

+0

@ BenVoigt: Sì, il tuo completamente giusto. Volevo scriverlo come una fodera e rimossi per errore tutta la magia. Il trucco è creare una copia da "questo". Nell'esempio: 'A ret = * this; ret * = rhs; return ret; ' – Paranaix

risposta

13

Come ha detto Lucian, non è possibile associare un oggetto temporaneo a un riferimento non const. L'aspettativa del compilatore è che l'oggetto cesserà di esistere dopo l'espressione, quindi non ha senso modificarlo.

per risolvere il tuo codice, rimuovere il temporaneo (rendendo l'argomento const& non ha senso in operator *=):

A operator*(A a, const A& b) 
{ 
    return a *= b; 
} 
+0

@ Ben ho bisogno del caffè ... Per difendere il mio onore, questo (passa per valore) è come lo scriverei normalmente quando sono sveglio. –

+0

Molto più semplice. E più ottimizzato, poiché può muoversi quando il parametro attuale è un valore x. –

5

Quando si scrive A(a), si crea un temporanea di tipo A (a rvalue) che si copia -costruzione con a. C++ afferma che nessun valore può essere passato come riferimento non const. Visual Studio è un po 'trascurato su questa regola, ma gcc e simili lo rafforzano.

Per risolvere, provare questo (che è esattamente lo stesso, ma si crea un lvalue denominando tale variabile). Altro su L e R-valore here

A operator*(A a, const A& b) 
{ 
    return a *= b; 
} 
+2

La stessa obiezione che ho postato sulla risposta di Konrad. –

+0

Entrambi sono corretti. Ma a volte, non è necessario creare una copia di a per eseguire l'operazione *. per esempio. L'operatore Vector * non utilizzerà * = per esprimere * – crazyjul

+0

"Visual Studio è un po 'trascurato su questa regola ...": Visual Studio lo rileva se stai utilizzando il livello di avviso 4/tratta gli avvisi come errori (come è saggio) . – mwigdahl