Вот очень простая иерархия классов:Где должен? = Оператор быть определен в иерархии классов?
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;
};
Как вы можете видеть, оператор = определен в базовом классе. Поскольку я очень ленив, я не хочу дублировать такой простой код во всех производных классах.
Unfortunatley, с этим кодом:
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
возвращает ложь, потому что он выполняет A::operator!=
, который вызывает то A::operator==
, а не B::operator==
(даже если оператор является виртуальным, вытекающим параметр версии класса отличается, они не связанных в vtable).
Так какой лучший способ адресовать? = Оператор в общем случае для иерархии классов?
Одно решение повторить его в каждом классе, B
бы тогда:
virtual bool operator!=(const B& right) const
{
return !(*this == right);
}
Но это боль, когда у вас есть много классов .... У меня есть 30 ....
Другим решением было бы иметь общий шаблон подход:
template <class T>
bool operator!=(const T& left, const T& right)
{
return !(left == right);
}
Но это обходит любой !=
оператор, определяемый любым классом .... так что это может быть опасно, если один decla по-другому (или если объявлено ==
, вызывающее !=
, это закончится бесконечным циклом ...). Поэтому я считаю, что это решение очень опасно ... за исключением того, что мы можем ограничить шаблон, который будет использоваться для всех классов, полученных из класса верхнего уровня нашей иерархии (A
в моем примере) .... но я не думаю, что это выполнимо вообще.
Примечание: Я не использую C++ 11, но ... извините за это.
Кроме того, в настоящее время 'A (42) == B (42, 0)', поскольку вы сравниваете только часть 'A' ... – Jarod42
Для большей ясности и обеспечения того, чтобы A продолжал работать независимо (если вы не используете" t хочу, вам не нужно выводить B из него), реализовать! = для A, B, C, D и того, что у вас есть в вашей иерархии. Опять же, если они вам не нужны, зачем вам вообще вообще выходить? – Robinson