【发布时间】:2014-11-06 08:09:51
【问题描述】:
我正在尝试使用 void* 指针将不同的对象存储在一个全局表中。问题是如何取回 void* 对象。如果我有一个公共基类,比如 Object ,我总是可以将 void* 指针存储为 Object,然后再转换回 Object*。从 Object* 我可以进一步转换为特定类型。
class Object{};
class A : public Object{ virtual ~A()}
class B : public A { }
class C : public Object{ virtual ~C()}
class D: public C{};
A* aObj = new B;
void* v = static_cast<Object*>(aObj);
// scenario 1, try to get as A*
Object* obj = static_cast<Object*> (v);
A* vaobj = dynamic_cast<A*> ( obj); // ok
// scenario 2, try to get it as C*
Object* obj = static_cast<Object*> (v);
C* caobj = dynamic_cast<C*> ( obj); // ok, caObj will be null so I can throw exception if this happens
我知道当我有一个公共基类时的解决方案是安全的,但问题是我不能有公共基类,因为我不能控制所有不同的类型,也不能从 Object 派生它们。我没有通用基类时的代码:
class A{ virtual ~A() }; class B : public A{};
class C{ virtual ~C() }; class D : public C{};
A* aObj = new B;
void* v = dynamic_cast<void*>(aObj);// to actually store the address of B
// scenario 1, try to retrieve object as A*
A* aObj2 = static_cast<A*>(v);
A* aa = dynamic_cast<A*> (aObj2); // aa should be non null
// scenario 2, try to retrieve object as C*
C* cObj = static_cast<C*>(v);
C* cc = dynamic_cast<C*>(cObj); // cc should be null
问题:
场景 1: 我将 void* 指针与 B 的地址一起存储(dynamic_cast 到 void* 确实如此)。然后我做 我知道带有 A* 的 static_cast 是不安全的,因为我最初将 void* ptr 中的对象存储为 B*,并且我知道我们必须在 void* 中存储和检索相同类型的指针。但是,然后我会进一步使用 dynamic_cast 进行强制转换,以验证该对象实际上是正确的。所以这应该可以工作,并且 dynamic_cast 应该给我正确的对象?
场景 2: 同样,但现在我先将 static_casting 转换为 C*,然后再进行 dynamic_casting,这次我应该得到 NULL,因为存储的对象实际上是 B。
【问题讨论】:
-
我会说“这闻起来很糟糕”。换句话说,您可能应该考虑其他一些解决方案。为什么需要将不相关的对象存储在表中?也许您应该存储一个包装器对象?
-
不,我绝对应该存储对象指针。所以我需要一些解决方案,我想这是常见问题,但很难解决
-
但是你最终不得不做一堆
if ptr != NULL ...,这不利于代码的可读性,也不利于性能。也许您可以解释您的实际问题是什么,而不是“您如何尝试解决它”,因为我很确定这是错误的解决方案。 (哦,dynamic_cast通常也很慢!) -
不,没关系,如果 ptr!=NULL,我不会有一堆检查,那将在一个地方,即从 void* 获取对象的请求应该来自一个模板函数,该函数将指定输入如何获得 void* 。在该函数中,如果 ptr == NULL,我将抛出异常。
标签: c++ void-pointers