considerare due puntatoricome verificare se due puntatori puntano allo stesso oggetto o no?
A* a;
B* b;
Sia A e B sono classi polimorfiche. Come verificare se a e b puntano allo stesso oggetto o no?
Più precisamente, specifichiamo a e b il punto sullo stesso oggetto se esiste qualche oggetto d di tipo D tale che sia * a che * b siano da qualche parte nella gerarchia di classi di d.
proporrei la seguente soluzione:
dynamic_cast<void*>(a) == dynamic_cast<void*>(b)
Infatti, secondo lo standard,
dynamic_cast<void*>(v)
rese “un puntatore all'oggetto massima derivazione puntato da v (n3242.pdf. : § 5.2.7 - 7). Se il più derivato per entrambi è lo stesso oggetto, i puntatori puntano allo stesso oggetto.
Sono abbastanza sicuro che dovrebbe sempre funzionare correttamente dal punto di vista pratico. Ma teoricamente, a prima vista l'uguaglianza proposta sembra produrre falsi positivi, per esempio, nel caso in cui b punti al primo membro di A (non all'antenato di A). Sebbene sia praticamente impossibile ottenere indirizzi uguali per A e il suo membro poiché il puntatore della tabella virtuale di A deve essere posizionato prima di questo membro, lo standard non impone tabelle virtuali e non dice nulla sul layout della classe.
Quindi, le mie domande sono:
E 'la soluzione proposta corretta dal punto di vista di serie?
Sono presenti avvertenze sull'ereditarietà privata (protetta) o sulla qualifica di cv?
Ci sono soluzioni migliori?
[EDIT]
ho cercato di presentare alcuni esempio che illustra uno scenario relativamente complessa. In questo caso il crosscasting dinamico e il casting statico sono ambigui.
// 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");
}
}
Perché non 'a == b'? – iammilind
@iammilind: A e B possono essere classi base per alcuni D ma non correlate tra loro – user396672
+1 per @iammilind - i vecchi 'uns sono i migliori! –