1

我需要将包含地址的整数类型转换为实际的指针类型。我可以使用 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);

使用第二种方法有什么好处吗?

4

8 回答 8

2

dynamic_cast不同的 C++ 实现以不同的方式实现类型检查;如果您想为您的特定实现提供答案,您应该提及您正在使用的实现。一般来说,回答这个问题的唯一方法是参考 ISO 标准 C++。

根据我对标准的阅读,调用dynamic_castvoid 指针是非法的:

dynamic_cast<T>(v)

“如果 T 是指针类型,则 v 应是指向完整类类型的指针的右值”

(来自 ISO C++ 标准的 5.2.7.2)。void不是完整的类类型,所以表达式是非法的。

有趣的是,被强制转换的类型被允许是一个 void 指针,即

void * foo = dynamic_cast<void *>(some_pointer);

在这种情况下,dynamic_cast总是成功,结果值是指向由 指向的最衍生对象的指针v

于 2009-12-02T10:42:12.837 回答
2

不,这样做没有特别的优势。你使用的那一刻reinterpret_cast,所有的赌注都被取消了。您可以确保演员阵容有效。

于 2009-12-02T10:26:34.660 回答
2

实际上并没有太大的优势。如果 void* 指向的不是指向多态对象的指针,那么您会立即遇到未定义的行为(通常是访问冲突)。

于 2009-12-02T10:26:49.417 回答
1

安全的方法是记录所有活动的 MyClass 对象。最好将此记录保存在 中std::set<void*>,这意味着您可以轻松地添加、删除和测试元素。

将它们存储为void*s 的原因是您不会冒像MyClass*从整数中创建未对齐指针那样的讨厌风险。

于 2009-12-02T10:35:38.807 回答
0
  • 首先,“重新解释”intvoid *一个坏主意。如果sizeof(int)是 4 和sizeof(void *)8(64x 系统),则它是格式错误的。

  • 此外dynamic_cast,仅对多态类的情况有效。

于 2009-12-02T10:42:46.423 回答
0

如果您确定它the_integer指向一个已知的基类(至少有一个虚拟成员),那么实际上可能有一个优势:知道该对象属于特定的派生类。但是你必须reinterpret_cast先到你的基类,然后做dynamic_cast

BaseClass* obj = reinterpret_cast<BaseClass*>(the_integer);
MyClass* myObj = dynamic_cast<BaseClass*>(obj);

使用void*indynamic_cast是没有用的,而且完全是错误的。您不能使用它dynamic_cast来检查内存中某个任意位置是否存在有效对象。

在将地址存储在非指针类型变量中时,您还应该注意。存在 sizeof(void*) != sizeof(int) 的架构,例如 LP64。

于 2009-12-02T10:48:38.310 回答
0

选项 1 是您唯一的(半)便携/有效选项。

选项 2:作为 dynamic_cast 的 C++ 无效(因为不允许使用 void)。

在实现级别,它需要来自源类型的类型信息才能到达目标类型。没有办法(或者可能没有办法)从 void* 获取运行时源类型信息,因此这也是无效的。

Dynamic_Cast 用于向上和向下转换不是来自未知类型的类型层次结构。

作为旁注,您可能应该使用 void* 而不是整数来存储无类型指针。int 有可能不足以存储指针。

于 2009-12-02T10:56:38.343 回答
0

在 C++ 中处理指针的最安全方法是类型安全地处理它们。这表示:

  • 切勿将指针存储在指针以外的任何地方
  • 避免空指针
  • 永远不要将指针传递给其他进程
  • 如果您打算在线程上使用指针,请考虑 weak_ptr

这样做的原因是:您计划做的事情是不安全的,除非您与不安全(遗留?)代码交互,否则可以避免。在这种情况下,请考虑 MSalters 的回答,但请注意,这仍然很麻烦。

于 2009-12-02T10:58:57.187 回答