2012-04-19 14 views
12

Kiedy próbuję skompilować następujący (g ++ 4.6.3)Przeciążanie operatora C++: brak znanej konwersji z obiektu na odniesienie?

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; 
} 

pojawia się błąd

/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&’ 

To mnie zastanawia - jak można konwersja z klasy do odniesienia do tej klasy nie wiadomo?

Zmiana deklaracji klasy A w następujący sposób nie ma żadnego wpływu:

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

sam błąd.

Byłbym niezwykle wdzięczny za wskazówki, co się tutaj dzieje.

+0

Możesz rozwiązać ten problem, deklarując operatora w zakresie klasy. Wtedy twój podpis metody wyglądałby tak: "Operator * (const A & rhs) const; ' Jeśli chcesz użyć operatora złożonego do implementacji, możesz napisać: 'return * this * = rhs' – Paranaix

+0

@Paranaix: Nie, nie możesz użyć 'operator * =' na '* this' wewnątrz' const' funkcja członka, ponieważ zmodyfikowałaby '* this'. –

+0

@BenVoigt: Tak, twoja zupełna racja. Chciałem napisać to jako jeden liniowiec i przez przypadek usunąłem całą magię. Sztuką jest stworzenie kopii z "tego". W przykładzie: "A ret = * this; ret * = rhs; return ret; ' – Paranaix

Odpowiedz

13

Tak jak powiedział Lucian, nie można powiązać obiektu tymczasowego z odwołaniem do niego. Oczekiwaniem kompilatora jest to, że obiekt przestanie istnieć po wyrażeniu, więc nie ma sensu go modyfikować.

Aby rozwiązać swój kod, usunąć tymczasowe (zrobienie argument const& nie ma sensu w operator *=):

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

@Ben Potrzebuję kawy ... Aby bronić mojego honoru, to (przekazywać według wartości) jest to, jak normalnie to piszę, gdy się obudzę. –

+0

Znacznie prostsze. I bardziej zoptymalizowany, ponieważ może się poruszać, gdy rzeczywisty parametr jest wartością x. –

5

Kiedy piszesz A(a), należy utworzyć tymczasowy typu A (A rvalue), który należy skopiować -konstruuj przy pomocy a. C++ stwierdza, że ​​żadna rwartacja nie może być przekazana jako non const reference. Visual Studio jest nieco zaniedbany w tej regule, ale gcc i tym podobne wymuszają to.

Aby to naprawić, wypróbuj to (co jest dokładnie takie samo, ale utworzymy wartość l, nadając nazwę tej zmiennej). Więcej informacji o wartości l i r here

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

Taki sam zarzut, jak napisałem o odpowiedzi Konrada. –

+0

Obie są poprawne. Ale czasami nie trzeba tworzyć kopii a, aby wykonać operację *. na przykład Operator * nie użyje * = do wyrażenia * – crazyjul

+0

"Visual Studio jest nieco zaniedbany w tej regule ...": Visual Studio łapie to, jeśli używasz na poziomie ostrzeżenia 4/traktujesz ostrzeżenia jako błędy (co jest mądre) . – mwigdahl

Powiązane problemy