Angenommen, ich habe die folgende Klassenhierarchie:Was ist der richtige Weg, um den Operator == für eine Klassenhierarchie zu überladen?
class A
{
int foo;
virtual ~A() = 0;
};
A::~A() {}
class B : public A
{
int bar;
};
class C : public A
{
int baz;
};
Was ist der richtige Weg operator==
für diese Klassen zu überlasten? Wenn ich alle freien Funktionen mache, können B und C die Version von A nicht ohne Casting nutzen. Es wäre auch jemand zu tun, einen tiefen Vergleich nur Verweise auf A. unter verhindern Wenn ich sie virtuelle Member-Funktionen zu machen, dann eine abgeleitete Version könnte wie folgt aussehen:
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;
}
}
Wieder warf ich habe immer noch (und es fühlt sich falsch an). Gibt es einen bevorzugten Weg, dies zu tun?
Update:
Es gibt nur zwei Antworten so weit, aber es sieht aus wie der richtige Weg, um den Zuweisungsoperator ist analog:
- Machen Sie nicht-Blatt Klassen abstrakt
- Protected nicht-virtuellen in den nicht-Blatt-Klassen
- öffentliche nichtvirtuellen in dem Blatt Klassen
Jeder Benutzer, der versucht, zwei Objekte unterschiedlicher Typen zu vergleichen, wird nicht kompiliert, da die Basisfunktion geschützt ist, und die Blattklassen können die Version des übergeordneten Elements verwenden, um diesen Teil der Daten zu vergleichen.
Dies ist ein klassisches Double-Dispatch Problem. Entweder ist Ihre Hierarchie vorher bekannt, in diesem Fall müssen Sie n * (n - 1)/2 Funktionen schreiben, oder nicht und Sie müssen einen anderen Weg finden (z. B. einen Hash des Objekts zurückgeben und Hashes vergleichen). –