我需要将包含地址的整数类型转换为实际的指针类型。我可以按如下方式使用reinterpret_cast:
MyClass *mc1 = reinterpret_cast<MyClass*>(the_integer);
但是,这不执行任何运行时检查以查看有问题的地址是否实际上包含MyClass对象。我想知道在第一次转换为void *(使用reinterpret_cast)然后在结果上使用dynamic_cast时是否有任何好处。像这样:
void *p = reinterpret_cast<void*>(the_integer);
MyClass *mc1 = dynamic_cast<MyClass*>(p);
assert(mc1 != NULL);
使用第二种方法有什么优势吗?
答案 0 :(得分:2)
不,这样做没有特别的优势。您使用reinterpret_cast
的那一刻,所有赌注都已关闭。这取决于你,以确保演员阵容有效。
答案 1 :(得分:2)
答案 2 :(得分:2)
dynamic_cast
上的类型检查由不同的C ++实现以不同的方式实现;如果您想要特定实现的答案,您应该提到您正在使用的实现。回答问题的唯一方法是参考ISO标准C ++。
通过阅读标准,在void指针上调用dynamic_cast
是非法的:
dynamic_cast<T>(v)
“如果T是指针类型,则v应为指向完成类类型的指针的右值”
(来自ISO C ++标准的5.2.7.2)。 void
不是完整的类类型,因此表达式是非法的。
有趣的是,允许将转换为的类型为空指针,即
void * foo = dynamic_cast<void *>(some_pointer);
在这种情况下,dynamic_cast
总是成功,结果值是指向v
指向的派生程度最高的对象的指针。
答案 3 :(得分:1)
安全的方法是保存所有实时MyClass对象的记录。最好将此记录保存在std::set<void*>
中,这意味着您可以轻松添加,删除和测试元素。
将它们存储为void*
的原因是你不会冒失败的风险,比如从整数中创建未对齐的MyClass*
指针。
答案 4 :(得分:0)
首先,将int
重新解释为void *
是一个坏主意。如果sizeof(int)
为4且sizeof(void *)
为8(64x系统),则表示格式不正确。
此外dynamic_cast
仅对多态类的情况有效。
答案 5 :(得分:0)
如果您确定the_integer
指向已知的基类(至少有一个虚拟成员),那么实际上可能有一个优点:知道该对象属于特定的派生类。但是您必须首先reinterpret_cast
到基类,然后执行dynamic_cast
:
BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);
在void*
中使用dynamic_cast
是没用的,而且完全错了。您无法使用dynamic_cast
检查内存中某个任意位置是否存在有效对象。
在非指针类型变量中存储地址时也应注意。存在sizeof(void *)!= sizeof(int)的体系结构,例如, LP64。
答案 6 :(得分:0)
选项1是您唯一的(半)便携/有效选项。
选项2:无效C ++作为dynamic_cast(不允许使用void)。
在实现级别,它需要源类型的类型信息才能到达目标类型。没有办法(或者没有办法)从void *中获取运行时源类型信息,因此这也是无效的。
Dynamic_Cast用于在类型层次结构中上下移动,而不是来自未知类型。
作为旁注,您可能应该使用void *而不是整数来存储无类型指针。 int有可能不足以存储指针。
答案 7 :(得分:0)
在C ++中处理指针的最安全的方法是处理它们的类型安全。这意味着:
原因是:您计划做的是不安全的,除非您与不安全(遗留?)代码接口,否则可以避免。在这种情况下考虑MSalters的答案,但要注意它仍然是一个麻烦。