我试图用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: 我存储带有地址B的void *指针(dynamic_cast为void *)。那我呢 static_cast with A *我知道它不安全,因为我最初将对象存储在void * ptr中作为B *,我知道我们必须在void *中存储和检索相同类型的指针。但是,然后我进一步使用dynamic_cast进行演员验证对象实际上是正确的。所以这应该工作,dynamic_cast应该给我正确的对象吗?
场景2: 同样,但现在我把拳头static_casting转换为C *,然后进一步dynamic_casting,这次我应该得到NULL,导致存储的对象实际上是B。
答案 0 :(得分:0)
在C ++中几乎不需要存储void *,而在C中它是常见的。 C ++有更好的,更类型安全的替代品。例如,也许你可以使用Boost.Any?
答案 1 :(得分:0)
正如许多评论者已经说过的那样,在C ++中存储void *实际上并不是必需的。如果您无法控制您要存储的类型,请为它们制作容器。这样你就可以控制它的定义和行为(如果你愿意的话,可以从Object派生它。)
非常粗糙的工作示例:
#include <iostream>
#include <string>
using namespace std;
class Object{
public:
virtual ~Object(){};
};
template<typename T>
class Container : public Object{
T* v;
public:
Container(T* b):v(b){}
T* value(){
return v;
}
void deleteContained(){
delete v;
}
};
class foo{
public:
virtual string say(){
return "foo";
}
};
class bar: public foo{
public:
string say(){
return "bar";
}
};
int main(){
Object* o;
o = new Container<foo>(new bar);
Container<foo>* fooCon = dynamic_cast<Container<foo>*>(o);
foo* fooObj = fooCon->value();
// Since you now have the object in a foo*, you can dynCast it to a bar* if you like.
bar* barObj = dynamic_cast<bar*>(fooObj);
// Cast to the wrong container type is NULL.
Container<int>* nullInt = dynamic_cast<Container<int>*>(o);
if(nullInt)
cout << "Cast Successful." << endl;
else
cout << "Cast failed." << endl;
// Both will print "bar", since "o" contains a bar object.
cout << fooObj->say() << endl;
cout << barObj->say() << endl;
((Container<foo>*)o)->deleteContained();
delete o;
}
输出:
Cast failed.
bar
bar