A* a;
B* b;
A和B都是多态类。如何检查a和b是否指向同一对象?
更精确地说,如果存在类型为D的对象d,使得*a和*b都在d的类层次结构中,则指定a和b指向同一对象。
我建议采用以下解决方案:
dynamic_cast<void*>(a) == dynamic_cast<void*>(b)
的确,根据标准,
dynamic_cast<void*>(v)
产生yield的结果是“指向 v 所指对象的最派生对象的指针”(引自n3242.pdf: §5.2.7 - 7)。
如果两个指针都指向同一个最派生对象,那么这两个指针指向同一个对象。
从实用角度看,我相信这个提议应该始终能正常工作。但从理论上来看,乍一看这个提议似乎会产生误判,例如当 b 指向 A 的第一个成员(而不是A的祖先)时。虽然因为A的虚函数表指针应该位于这个成员之前,A和其成员获得相同地址在实践中几乎不可能,但标准并未规定虚函数表,并且对类布局没有任何要求。
所以,我的问题如下:
从标准的角度来看,这个提议是否正确?
私有 (protected) 继承或 cv-qualification 是否存在任何注意事项?
是否有更好的解决方案?
[编辑]
我试图展示一个说明相对复杂情境的例子。在这种情况下,动态交叉转换和静态转换是有歧义的。
// 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");
}
}
a == b
? - iammilinda == b
不足以满足您的情况,我很想看到一个简单的自编译示例程序(特别是指针的静态类型和类层次结构),以比英语更准确地说明这种情况。 - Frerich Raabestruct A { int a; virtual ~A(); }; struct B { int b; virtual ~B(); }; struct C: A, B {}; int main() { C c; A *a = &c; B *b = &c; }
。现在,尽管a
和b
是指向同一对象的不同基类,但它们不能进行比较。(void*)a != (void*)b
,但是dynamic_cast<void*>(a) == dynamic_cast<void*>(b)
。这就是指针比较和提问者询问的问题之间的差异。 - Steve Jessop