为什么我会用dynamic_cast投射到空隙*

Why would I use dynamic_cast to cast TO a void *?

本文关键字:cast dynamic 为什么      更新时间:2023-10-16

所以我正在阅读"void *"中dynamic_cast的答案,虽然你不能从void *投射到T *但有几个回应指出,可以将T *投射到void *,但没有给出任何指示为什么要这样做。

这只是一些可能的琐事,还是有没有有意义的情况?我想过也许是为了可读性或明确表示我们正在转换为void *,但考虑到dynamic_cast的目的,它不太适合我。

就此而言,除了让T *隐含地变得void *之外,还有什么理由做其他事情吗?我见过 C 风格的强制转换,void *不时用于此目的,我认为只是明确(假设我们没有做一些不寻常的事情,比如将int转换为指针或其他东西(。

首先,当使用dynamic_cast<void*>(x)时,你会得到一个指向派生最多的对象的第一个字节的指针。只要静态类型的x是多态的。

这在少数情况下很有用,其中地址用作对象标识:

  • 现在,您可以完全区分指向同一对象的子对象的指针和指向不相关子对象的指针。
  • 您现在可以浏览一些扭曲的图形,而无需多次访问同一对象......可用于序列化
当然,

这当然不是日常用法,但C++内存地址是对象事实上的标识符,因此从继承层次结构的任何部分访问它的机制对于少数边缘情况肯定很有用。

这是有目的的,有点。它在允许它的规范部分中有所暗示。从 N3337 第 5.2.7 节第 7 段:

如果 T 是"指向 cv void 的指针",则结果是指向 v 指向的最派生对象的指针。

所以dynamic_cast<void*>(...)真的是static_cast<void*>(dynamic_cast<MostDerivedType*>(...))的简写.那会很有用...有点。

使其有用的困难在于您不一定知道MostDerivedType是什么。毕竟,每个表达式都可能不同。所以一旦你把它作为void*,你不一定有办法把它安全地扔回去。如果你对MostDerivedType进行猜测并static_cast它,而你错了,那么你就处于不确定的行为领域。而如果你对该类型执行dynamic_cast(然后static_cast void*(,如果它不是该类型,它至少会返回 NULL。

所以不,我会说它不是很有用。如果你想生活在C++的边界内,而不是依赖潜在的未定义行为,那就不行了。

在为运算符 newdelete 实现包装器时,它很有用。问题是运算符删除允许我们使用指向多态对象基数的指针来释放内存。在这种情况下,包装器将不知道哪个对象真正在那里被释放(在包装器之前分配的所有对象中(。所以我们使用 void *>(( dynamic_cast<</em> 作为对象的唯一标识 - 它转换为多态对象的最派生类型。这使我们能够跟踪当前通过此包装器分配的所有对象。此类包装器可用于内存分配跟踪和批量释放。