Предположим, что у меня есть следующая иерархия классов:
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;
}
}
Опять же, мне все равно приходится бросать (и это неправильно). Есть ли предпочтительный способ сделать это?
Update:
До сих пор есть только два ответа, но похоже, что правильный путь аналогичен оператору присваивания:
- Сделать неклассические классы абстрактными
- Защищенный не виртуальный в неклассических классах
- Публичная не виртуальная в классах листа
Любая попытка пользователя сравнить два объекта разных типов не будет компилироваться, потому что базовая функция защищена, а листовые классы могут использовать родительскую версию для сравнения этой части данных.