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
}
dynamic_cast<T>(v)
说道:
...
所以,不,不允许使用(void*)
值。
思考一下你的要求可能意味着什么:假设你有一个指针,真正指向一个Derived1*
,但是代码dynamic_cast
只知道它是一个void*
。假设您试图将其转换为指向Derived2*
的指针,其中两个派生类具有共同的基类。表面上看,您可能认为所有指针都将指向相同的Base
对象,其中包含对相关虚拟调度表和RTTI的指针,因此一切都可以相互关联。但是,请注意,派生类可能有多个基类,因此所需的Base
类子对象可能不是指向Derived*
所指向的对象。只能作为void*
- 这不起作用。结论:编译器需要知道这些类型,以便根据涉及的类型对指针进行一些调整。
Derived1* -----> [AnotherBase] [[VDT]Base] <-- 但是,需要一个指向开始的指针 [extra members] 这个子对象用于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);
}
无法将类型为“void *”的 'p' 动态转换为类型为“struct A*” 的内容(源不是指向类的指针)
除了Tony的不错的回答之外,这段代码片段出乎意料地帮助了我。首先,我们建立了一个简单的层次结构。然后,我们看看 dynamic_cast
是否能够“承受”一个 static_cast
。在这个实验之前,我认为“运行时类型信息是存在的,dynamic_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)))));
}
dynamic_cast
弄混了,它可以将指针转换为void*
类型。这是合法的,并且可以获得指向最终派生类对象的指针。void*
进行dynamic_cast
是不合法的 - 要转换的类型必须是多态的 - 至少包含一个虚函数(虚析构函数也算)。你可以将指向多态类型的指针转换为void *
,但反之则不行。