据此,void*
没有 RTTI 信息,因此铸造 from是void*
不合法的并且是有意义的。
如果我没记错的话,dynamic_cast
fromvoid*
正在研究 gcc。
你能澄清一下这个问题吗?
dynamic_cast
仅适用于多态类型,即包含虚函数的类。
在 gcc 中,您可以dynamic_cast
但 void*
不能来自:
struct S
{
virtual ~S() {}
};
int main()
{
S* p = new S();
void* v = dynamic_cast<void*>(p);
S* p1 = dynamic_cast<S*>(v); // gives an error
}
其中5.2.7 - Dynamic cast [expr.dynamic.cast]
说dynamic_cast<T>(v)
:
T
是指针类型,v
则应是指向完整类类型的指针的右值T
是引用类型,v
则应是完整类类型的左值(感谢 usta 对我遗漏的评论)...
v
应为指向多态类型的指针或左值所以,不,一个(void*)
值是不允许的。
让我们考虑一下您的请求可能意味着什么:假设您有一个真正指向 a 的指针Derived1*
,但 code dynamic_cast
-ing 只知道它是 a void*
。假设您正在尝试将其强制转换为 a Derived2*
,其中两个派生类都有一个共同的基础。表面上,您可能认为所有指针都指向同一个Base
对象,该对象将包含指向相关虚拟调度表和 RTTI 的指针,因此一切都可以挂在一起。但是,考虑到派生类可能有多个基类,因此所需的Base
类子对象可能不是Derived*
- 仅作为void*
- 正在指点。它行不通。结论:编译器需要知道这些类型,以便它可以根据所涉及的类型对指针进行一些调整。
Derived1* -----> [AnotherBase] [[VDT]Base] <-- 但是,需要一个指针来开始 [额外成员] dynamic_cast 的这个子对象
(一些答案谈到需要您要转换的指针是多态类型,具有虚函数。这都是有效的,但有点误导。正如您在上面看到的,即使它void*
是这样的类型如果没有完整的类型信息,仍然无法可靠地工作,因为真正的问题是它void*
可能指向派生对象的开始,而您需要一个指向派生类型的基类子对象的指针。 )
这是真的,void*
不能dynamically_cast
从。
你可能记错了。使用 g++ 4.5 和以下代码
struct A {
virtual ~A();
};
int main() {
A a;
void *p = &a;
A* pa = dynamic_cast<A*>(p);
}
我收到以下错误:
不能 dynamic_cast 'p' ('void*' 类型) 类型 'struct A*' (source 不是指向类的指针)
我猜你混淆了dynamic_cast
to void*
。这是合法的,并获得指向最派生类对象的指针。
dynamic_cast
from void*
是非法的 - 转换的类型必须是多态的 - 至少包含一个虚拟函数(虚拟析构函数也很重要)。
为了补充托尼的好答案,这个小代码片段出于某种原因帮助了我。首先,我们建立一个简单的层次结构。然后,我们看看是否dynamic_cast
可以“生存”一个static_cast
. 在这个实验之前,我认为“运行时类型信息在那里,动态转换应该弄清楚它。” 现在我意识到“dynamic_cast
必须根据编译器知道的一些表来查找它的信息,所以它不可能有什么神奇的力量。”
#include <iostream>
#include <cassert>
using namespace std;
class A {
protected:
virtual void foo() { cout << "A" << endl; }
};
class B1 : public A {
private:
virtual void foo() override { cout << "B1" << endl; }
};
class B2 : public A {
public:
virtual void foo() override { cout << "B2" << endl; }
};
int main(int argc, char **argv) {
B1 b1;
// undefined behavior even though dynamic_cast didn't return null
dynamic_cast<B2*>(
static_cast<B2*>(
static_cast<A*>(&b1)))->foo();
// dynamic_cast returns null here though
assert (!dynamic_cast<B2*>
(static_cast<A*>
(static_cast<B2*>
(static_cast<A*>(&b1)))));
}
您可以将指向多态类型的指针强制转换为void *
,但反之则不行。