我如何从void *指针中动态施放
How do I dynamically cast from a void * pointer generically?
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*
指针指向派生类指针时,我会收到以下错误:
无法dynamic_cast'vbase'(类型为'void*')键入'类派生*'(源不是类的指针)
我已经搜索了Stackoverflow,并遵循建议,通过在基类中实现虚拟功能以避免错误。我究竟做错了什么?这完全可以吗?
我的总体意图是使用void*
指针将任何传入的对象类型投入到派生类类型中。我希望你明白我的意思。
例如:
void dynamicCast(void * vptr)
{
BASE * pbase = new DERIVED;
DERIVED * pder;
pder = dynamic_cast<DERIVED *>(vbase);
}
我应该能够将任何类型的指针传递给dynamicCast
函数,并应将其转换为派生的类指针。
我认为有一个设计或/和理解问题
正如解释的那样,您无法从void*
中 dynamic_cast
。
为什么?因为dynamic_cast
需要一些运行时类型信息(RTTI)才能进行铸件(有关更多详细信息,请参见此链接)。仅在void*
中,C 代码没有机会知道此信息在哪里。最低限度是使用具有此类RTTI信息的对象的指针。
此信息是创建并与至少一个虚拟方法的任何类别的。如果没有虚拟方法,则不包含此信息。这就是为什么此不工作的原因:
struct A
{
};
struct B : A
{
};
int main()
{
B b;
A *a = &b;
dynamic_cast<B *>(a); // YOUR COMPILE TIME ERROR
}
修复程序是在A中添加虚拟方法A。在这里,我添加了一个虚拟破坏者,因为这通常是一件好事
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);
在调试模式下,您将检查一切都还好,并且在使用-DNDEBUG
标志的发布模式下以删除assert
您仅使用static_cast
当您将指针转换为对象类型转换为指向void的指针时,该void指针的有效转换为。您不能在void
指针上使用dynamic_cast
,因为void
不是多态性类型,因此您可以使用static_cast
进行。这样:
BASE *pbase = new DERIVED;
void *vbase = pbase; // Ok; implicit conversion to void*
BASE *pbase1 = static_cast<BASE*>(vbase); // the cast is required
一旦您将指针恢复到BASE
,当然,您可以使用dynamic_cast
将其转换为派生类型的指针:
DERIVED *pder = dynamic_cast<DERIVED*>(pbase1);
您不能在void *
上使用dynamic_cast
。
从规范中,对于dynamic_cast<T>(v)
:
如果t是指针类型,则V是的prvalue>"完整类型" 的指针,结果是T型T型。...
您应该做的是让所有类都从同一多态基类(至少具有一个虚拟函数)BASE
衍生而来,并使用BASE *
而不是void *
。
您的通用链接列表应该像这样:
class Node
{
Node* next;
void* vdata;
}
这是严格要求的唯一数据结构,但是您可能需要一个圆形列表或一个基本节点来跟踪列表的结尾或双关联列表。
呼叫者通过一个void*,您创建一个新节点,设置" vdata"并将节点添加到列表中。
- 如果非动态变量被指针引用,何时超出范围?
- 在对象指针上调用 Delete 是否会递归删除其动态分配的成员
- 指针的 C++ 动态数组 - 何时需要使用它?
- 使用指针在存在特征库的情况下动态分配 c++ 中的矩阵
- 指针类型类成员的动态强制转换的恒定性是什么?
- 删除包含包含动态对象的 STL 容器的智能指针
- 带有模板问题的指针的动态数组
- 存储指向动态数组元素的指针
- 动态维度数组的 C++ 别名指针
- 尝试创建指向动态分配的字符数组的指针
- 我如何用智能指针动态升起和降低
- 将指针添加到成员对象中的指针动态阵列
- 指针动态分配(核心倾倒)
- 如何在C++中增大和缩小双指针动态数组
- 指向指针数组的指针(动态分配)
- 使用指针动态数组同时输出整数值列表
- 从方法指针动态创建泛型函数指针,推导返回值和参数
- 使用指针动态分配数组
- 双指针动态分配
- 如何使用指针动态分配内存