所以我正在阅读dynamic_cast from "void *"的答案,虽然您无法从void *
转换为T *
但有几个回复指出可以投出{ {1}}到T *
,但不要给出任何迹象为什么你想要这样做。
这可能是一种琐事,或者是否有意义?我想到可能是为了可读性或明确表示我们正在转换为void *
,但考虑到void *
的目的,它并不适合我。
就此而言,除了让dynamic_cast
隐含地成为T *
之外,还有什么理由可以做其他事吗?我已经看到为了这个目的不时使用的void *
的C风格的强制转换,我认为只是为了明确(假设我们没有做一些不寻常的事情,比如将void *
转换为指针或其他东西)。
答案 0 :(得分:10)
首先,当使用dynamic_cast<void*>(x)
时,您会获得指向最派生对象的第一个字节的指针。只要x
的静态类型是多态的。
这在少数场景中很有用,其中地址用作对象标识:
当然,这肯定不是日常使用,但在C ++中,内存地址是对象的事实上的标识符,因此从继承层次结构的任何部分访问它的机制当然是对于那些少数边缘情况很有用。
答案 1 :(得分:5)
有一个目的,有点。它在规范中允许它的部分暗示。从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 ++的边界内而不依赖于潜在的未定义行为,那就不是了。
答案 2 :(得分:0)
当为操作符 new 和 delete 实现包装器时,这很有用。关键是运算符 delete 允许我们使用指向多态对象基址的指针来释放内存。在这种情况下,包装器将不知道哪个对象真正被释放(在包装器之前分配的所有对象中)。因此,我们使用 dynamic_cast