Cześć :)
Mam klasę a w niej zdefiniowane operatory:
bool(), ==
Teraz jeżeli porównuję obiekty tej klasy to są wywoływane tylko operatory bool(), a == jest nietknięte.
Dlaczego tak dziwnie
A JAK je porównujesz?
struct Foo {
int bar;
explicit operator bool() const { std::cout << "operator bool()" << std::endl; return bar != 0; } // albo safe bool idiom
bool operator== (const A& rhs) { std::cout << "operator ==()" << std::endl; return bar == rhs.bar; }
bool operator!= (const A& rhs) { std::cout << "operator !=(const Foo&)" << std::endl; return !(*this == rhs); }
};
int main() {
Foo f, g;
g.bar = 1;
f.bar = 0;
if (f) {} // out: operator bool()
if (g) {} // out: operator bool()
if ( f == g) {} // out: operator ==(const Foo&)
// if (g < 1) {}
return 0;
}
Uhm, @Satirev, dając "explicit" przy bool większość magicznych problemów się rozwiązuje, ale troszkę wylewając dziecko razem z kąpielą ;) Bo takie coś nie przejdzie:
int main() {
Foo f;
bool z = true;
if( z == f) { // błąd kompilacji tutaj!
// ...
}
Za to wywalając explicit
robi się bardzo złośliwie czasem, jeśli się o const'ach zapomni.
struct Foo {
int bar;
operator bool() const { ... }
bool operator== (const A& rhs) { ... }
bool operator!= (const A& rhs) { ... }
};
bool something(const Foo& a , const Foo& b) {
return a == b; // tutaj operator porównania nie ma prawa ruszyć
}
Ze względu na to, że operator== nie posiada const
, a zmienna a
jest const
... to kompilator chętniej ruszy z operatorami konwersji, a dopiero wynik konwersji zacznie porównywać. Czyli wypadałoby te operatory dać jako:
bool operator!= (const A& rhs) const { ... }
// zamiast
bool operator!= (const A& rhs) { ... }
Ale ponieważ operator bool jest naprawdę patologiczny, to explicit jest najlepsiejszym wyjściem. Właśnie z powodu bool'owych problemów i sprytnych prób ich ominięcia można skompilować w C++ takie głupoty jak std::string(false)
albo delete std::cout
.
Dzięki! :D