Betrachten wir zwei Zeigerwie überprüft man, ob zwei Zeiger auf dasselbe Objekt zeigen oder nicht?
A* a;
B* b;
Sowohl A als auch B sind polymorph Klassen. Wie überprüft man, ob a und b auf dasselbe Objekt zeigen oder nicht?
Genauer gesagt, geben wir a und b auf dasselbe Objekt, wenn ein Objekt d vom Typ D existiert, so dass sowohl * a als auch * b irgendwo in der Klassenhierarchie von d stehen.
würde ich die folgende Lösung vor:
dynamic_cast<void*>(a) == dynamic_cast<void*>(b)
der Tat nach der Norm,
dynamic_cast<void*>(v)
yields „ein Zeiger auf den meisten abgeleitetes Objekt durch v zeigte (n3242.pdf. : § 5.2.7 - 7). Wenn das am meisten abgeleitete für beide dasselbe Objekt ist, zeigen die Zeiger auf dasselbe Objekt.
Ich bin mir ziemlich sicher, dass es aus der praktischen Sicht immer richtig funktionieren sollte. Aber theoretisch scheint die vorgeschlagene Gleichheit auf den ersten Blick falsch positiv zu sein, zum Beispiel wenn b auf das erste Mitglied von A zeigt (nicht auf A's Vorfahren). Obwohl es praktisch unmöglich ist, gleiche Adressen für A und sein Mitglied zu erhalten, da sich der virtuelle Tabellenzeiger von A vor diesem Mitglied befinden sollte, schreibt der Standard keine virtuellen Tabellen vor und sagt nichts über das Klassenlayout aus.
Also, meine Fragen sind:
ist die vorgeschlagene Lösung aus dem Standard-Sicht richtig?
Gibt es irgendwelche Vorbehalte gegenüber privater (geschützter) Erbschaft oder CV-Qualifikation?
Gibt es bessere Lösungen?
[EDIT]
Ich habe versucht, einige Beispiele zu präsentieren, die ein relativ komplexes Szenario veranschaulicht. In diesem Fall sind dynamisches Crosscasting und statisches Casting mehrdeutig.
// proposed impplementation:
template<typename P, typename Q>
bool test_ptrs(const P* p, const Q* q)
{
return (dynamic_cast<const void*>(p) == dynamic_cast<const void*>(q));
}
struct Root
{
virtual ~Root(){};
};
struct A: public Root // nonvirtually
{
};
struct B: public Root // nonvirtually
{
};
struct C: public A, B // nonvirtual diamond started with Root
{
Root another_root_instance;
};
int main()
{
C c;
A* pa= &c;
B* pb= &c;
bool b = (dynamic_cast<void*>(pa) == dynamic_cast<void*>(pb));
Root* pra= dynamic_cast<Root*> (pa);
Root* prb= dynamic_cast<Root*> (pb);
//Root* prc= dynamic_cast<Root*> (&c); // runtime error, ambiguous cast
Root* prr= dynamic_cast<Root*>(pra);
Root* pcar= dynamic_cast<Root*>(pra);
Root* pcbr= dynamic_cast<Root*>(prb);
if(
test_ptrs(pa, pb)
&& test_ptrs(pra, prb)
&& !test_ptrs(pa,&c.another_root_instance)
)
{
printf("\n test passed \n");
}
}
Warum nicht 'a == b '? – iammilind
@iammilind: A und B können Basisklassen für einige D sein aber nicht miteinander verwandt – user396672
+1 für @iammilind - die alten 'uns sind die besten! –