Tutaj jest bardzo prosta klasa hierarchia:Gdzie powinien! = Operator być zdefiniowany w hierarchii klas?
class A
{
public:
A(int _a) : a(_a) {}
virtual bool operator==(const A& right) const
{
return a == right.a;
}
virtual bool operator!=(const A& right) const
{
return !(*this == right);
}
int a;
};
class B : public A
{
public:
B(int _a, int _b) : A(_a), b(_b) {}
virtual bool operator==(const B& right) const
{
return A::operator==(right) && b == right.b;
}
int b;
};
Jak widać, operator = jest zdefiniowana w klasie bazowej. Ponieważ jestem bardzo leniwy, nie chcę duplikować takiego prostego kodu we wszystkich klasach pochodnych.
Unfortunatley, z tym kodem:
A a4(4), a5(5), a4bis(4);
assert(a4 == a4bis);
assert(a4 != a5);
B b1(4,5), b2(4,6);
assert(!(b1 == b2));
assert(b1 != b2); // fails because B::operator== is not called!
b1 != b2
zwraca false, ponieważ wykonuje A::operator!=
który wywołuje następnie A::operator==
zamiast B::operator==
(nawet jeśli operator wirtualny, gdyż pochodzą parametr wersja klasa jest inna, są one nie połączone w vtable).
Jaki jest najlepszy sposób na adres! = Operator w sposób ogólny do hierarchii klas?
Jednym z rozwiązań jest powtarzanie go w każdej klasie, B
musiałaby wówczas:
virtual bool operator!=(const B& right) const
{
return !(*this == right);
}
Ale to ból, gdy masz wiele klas .... Mam 30 ....
Innym rozwiązaniem byłoby mieć ogólne podejście szablon:
template <class T>
bool operator!=(const T& left, const T& right)
{
return !(left == right);
}
Ale ta omija żadnej !=
operatora zdefiniowanego przez jakiejkolwiek klasy .... więc może to być ryzykowne, jeśli jeden decla czerwony to inaczej (lub jeśli zadeklarowano, że ==
sam wywołuje !=
, skończyłoby się nieskończoną pętlą ...). Czuję, że to rozwiązanie jest bardzo niebezpieczne ... chyba że możemy ograniczyć szablon do użycia dla wszystkich klas wywodzących się z klasy najwyższego poziomu naszej hierarchii (A
w moim przykładzie) ... ale ja nie myślę, że jest to w ogóle wykonalne.
Uwaga: nie używam jeszcze C++ 11 ... przepraszam za to.
Co więcej, obecnie "A (42) == B (42, 0)", porównując tylko część "A" ... – Jarod42
Dla przejrzystości i zapewnienia, że A nadal działa niezależnie (jeśli nie t chcesz tego, nie musisz wywodzić z niego B), implementuj! = dla A, B, C, D i cokolwiek masz w swojej hierarchii. Znowu, jeśli ich nie potrzebujesz, dlaczego w ogóle musisz czerpać? – Robinson