Как правильно перегрузить оператор == для иерархии классов?

Предположим, у меня есть следующая иерархия классов:

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;
    }
}

Опять же, я все еще должен сыграть (и это неправильно). Есть ли предпочтительный способ сделать это?

Обновить:

Пока есть только два ответа, но похоже, что правильный путь аналогичен оператору присваивания:

Сделайте не листовые классы абстрактнымиЗащищено не виртуально в неконечных классахПубличные не виртуальные в листовых классах

Любая попытка пользователя сравнить два объекта разных типов не будет компилироваться, поскольку базовая функция защищена, и конечные классы могут использовать версию родительского объекта для сравнения этой части данных.

Ответы на вопрос(5)

Ваш ответ на вопрос