Как правильно перегрузить оператор == для иерархии классов?
Предположим, у меня есть следующая иерархия классов:
class A
{
int foo;
virtual ~A() = 0;
};
A::~A() {}
class B : public A
{
int bar;
};
class C : public A
{
int baz;
};
Как правильно перегрузитьoperator==
для этих классов? Если я сделаю их все бесплатные функции, то B и C не смогут использовать версию A без приведения. Это также помешало бы кому-либо сделать глубокое сравнение, имеющее только ссылки на A. Если я сделаю их виртуальными функциями-членами, тогда производная версия может выглядеть так:
bool B::operator==(const A& rhs) const
{
const B* ptr = dynamic_cast<const B*>(&rhs);
if (ptr != 0) {
return (bar == ptr->bar) && (A::operator==(*this, rhs));
}
else {
return false;
}
}
Опять же, я все еще должен сыграть (и это неправильно). Есть ли предпочтительный способ сделать это?
Обновить:
Пока есть только два ответа, но похоже, что правильный путь аналогичен оператору присваивания:
Сделайте не листовые классы абстрактнымиЗащищено не виртуально в неконечных классахПубличные не виртуальные в листовых классахЛюбая попытка пользователя сравнить два объекта разных типов не будет компилироваться, поскольку базовая функция защищена, и конечные классы могут использовать версию родительского объекта для сравнения этой части данных.