class BASE {
public:
virtual ~BASE() {}
void lamp() {
cout << "\nBASE CLASS";
}
};
class DERIVED : public BASE {
public:
void fun();
};
void DERIVED::fun() {
cout << "\nDERIVED CLASS!";
}
int main() {
BASE * pbase = new DERIVED; //BASE CLASS POINTER
void * vbase = pbase; //VOID POINTER TAKING BASE POINTER
DERIVED * pder; //DERIVED CLASS POINTER
//pder = static_cast<DERIVED *>(vbase); //THIS WORKS
pder = dynamic_cast<DERIVED *>(vbase); //THIS DOESN'T
pder->lamp();
pder->fun();
return 0;
}
每当我尝试将 void*
指针动态转换为派生类指针时,我都会收到以下错误:
cannot dynamic_cast 'vbase' (of type 'void*') to type 'class DERIVED*' (source is not a pointer to class)
我搜索了 StackOverflow 并听从了建议,在基类中实现了一个虚函数以避免错误。我究竟做错了什么? 这可能吗?
我的总体意图是使用 void*
指针将任何传入的对象类型转换为派生类类型。我希望你明白我的意思。
例如:
void dynamicCast(void * vptr)
{
BASE * pbase = new DERIVED;
DERIVED * pder;
pder = dynamic_cast<DERIVED *>(vbase);
}
我应该能够将任何类型的指针传递给 dynamicCast
函数,并且它应该被转换为派生类指针。
最佳答案
我认为存在设计或/和理解问题
如前所述,您不能从 void*
中dynamic_cast
。
为什么?因为 dynamic_cast
需要一些运行时类型信息 (RTTI) 来执行转换(更多详细信息请参见 this link)。仅从 void*
来看,C++ 代码没有机会知道此信息在哪里。最低限度是使用指向具有此类 RTTI 信息的对象的指针。
创建此信息并将其绑定(bind)到具有至少一个虚方法 的任何类。如果没有虚拟方法,则不包括此信息。这就是为什么这不工作的原因:
struct A
{
};
struct B : A
{
};
int main()
{
B b;
A *a = &b;
dynamic_cast<B *>(a); // YOUR COMPILE TIME ERROR
}
解决方法是向 A 添加一个虚拟方法。这里我添加了一个虚拟析构函数作为 this is generally a good thing。
struct A
{
virtual ~A() = default;
};
struct B : A
{
};
int main()
{
B b;
A *a = &b;
dynamic_cast<B *>(a); // OK
}
另请注意,dynamic_cast
允许您检查转换是否合法。
例如我们可以添加一个C类并检查:
struct C
{
};
int main()
{
B b;
A *a = &b;
assert(dynamic_cast<B *>(a)!=nullptr); // OK
assert(dynamic_cast<C *>(a)==nullptr); // OK can not cast A to C
}
这种运行时操作不是免费的。如果你搜索最大速度可以使用这个技巧:
assert(dynamic_cast<B *>(a)!=nullptr);
B* b=static_cast<B*>(a);
在 Debug模式下,您将检查是否一切正常,在 Release模式下,使用 -DNDEBUG
标志来删除 assert
您将只使用 static_cast
关于c++ - 一般如何从 void * 指针动态转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45950712/