为了避免X Y情况,我正在尝试验证void*
指针强制转换是否有效。
为了解决这个问题,我想使用dynamic_cast
的属性。
给出以下代码:
class A
{
virtual void foo(){}
};
class B
{
virtual void bar(){}
};
void* createA() { return new A();}
void* createB() { return new B();}
int main()
{
A* ptr =reinterpret_cast<A*>(createA());
A* ptr2 = reinterpret_cast<A*> (createB());
ptr = dynamic_cast<A*>(ptr); // not NULL as expected
ptr2 = dynamic_cast<A*> (ptr2); // was expecting NULL, however it's a valid pointer
}
如果RTTI不是预期的类型,那么dynamic_cast是否应该以NULL失败?
答案 0 :(得分:3)
解决此类问题的常用方法是给A
和B
一个公共标记基类/接口。 void*
不保留任何类型信息。此外,reinterpret_cast<>
只会覆盖任何可能存在的类型信息。
您可以这样做:
class Base {
public:
virtual ~Base() {}
};
class A : public Base
{
virtual void foo(){}
};
class B : public Base
{
virtual void bar(){}
};
Base* createA() { return new A();}
Base* createB() { return new B();}
int main()
{
Base* ptr = createA();
Base* ptr2 = createB();
ptr = dynamic_cast<A*>(ptr); // not NULL as expected
ptr2 = dynamic_cast<A*> (ptr2); // NULL pointer now
}
答案 1 :(得分:2)
dynamic_cast
不能用于检查指向任意内存地址的指针是否指向特定类型的对象。 dynamic_cast
将通过检查指向的对象的RTTI来执行转换,仅在此对象的类型可能位于要转换为的类型的继承链中的情况下执行。在您的示例中,即使B *
实际指向A *
,B *
到A
也会始终生成nullptr:
A * a_ptr = dynamic_cast<A*>(reinterpret_cast< B* >(createA()));
assert(nullptr == a_ptr);
此外,您正在尝试将A *
投射到A *
,这基本上会导致noop:
5.2.7动态演员[expr.dynamic.cast]
3如果v的类型与T相同,或者它与T相同,除了T中的类对象类型比v中的类对象类型更符合cv,结果为v(如果必要)。