C++ 将不同的对象存储为void*并在void之间进行转换*
我试图用void*指针将不同的对象存储在一个全局表中。问题是如何取回void*对象。如果我有一个公共基类,比如Object,我总是可以将void*指针存储为Object,然后再转换回Object*。从Object*我可以进一步转换为特定类型C++ 将不同的对象存储为void*并在void之间进行转换*,c++,void-pointers,C++,Void Pointers,我试图用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: pu
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
类对象{};
类A:公共对象{virtual~A()}
B类:公共A{}
类C:公共对象{virtual~C()}
D类:公共C{};
A*aObj=新的B;
void*v=静态铸件(aObj);
//场景1,尝试作为一个*
Object*obj=静态_cast(v);
A*vaobj=动态铸造(obj);//好啊
//场景2,尝试将其设置为C*
Object*obj=静态_cast(v);
C*caobj=动态铸造(obj);//好的,caObj将为null,所以如果发生这种情况,我可以抛出异常
我知道当我有一个公共基类时,解决方案是安全的,但问题是我不能有公共基类,因为我不能控制所有不同的类型,也不能从对象派生它们。没有公共基类时的代码:
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
class A{virtual~A()};B类:公共A{};
类C{virtual~C()};D类:公共C{};
A*aObj=新的B;
void*v=动态(aObj);//实际存储B的地址
//场景1,尝试将对象作为*
A*aObj2=静态_型铸造(v);
A*aa=动态_cast(aObj2);//aa应该是非空的
//场景2,尝试将对象检索为C*
C*cObj=静态铸造(v);
C*cc=动态_铸造(cObj);//cc应该为null
问题:
情景1:
我存储了地址为B的void*指针(该动态_转换为void*所做的)。那我会的
静态_强制转换为A*,我知道这是不安全的,因为我最初将对象作为B*存储在void*ptr中,并且我知道我们必须在void*中存储和检索相同类型的指针。但是,然后我使用dynamic_cast进行进一步的强制转换,以验证对象实际上是正确的。所以这应该行得通,而dynamic_cast应该给我正确的对象
情景2:
同样的,但是现在我是拳头静态的C++,然后再动态的转换,这次我应该得到null,因为存储对象实际上是B.< /P> < P>存储空洞*几乎是不必要的C++,而C是普通的。C++有更好的、更安全的类型选择。例如,也许你可以使用Booost。任何?< P>很多评论者已经说过,在C++中存储空洞是没有必要的。如果您无法控制正在存储的类型,请为它们制作一个容器。这样,您就可以控制它的定义和行为(如果您愿意,还可以从对象派生它) 非常粗略的工作示例:
#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;
}
我会说“这闻起来很难闻”。换句话说,您可能应该考虑其他解决方案。为什么需要在表中存储不相关的对象?也许你应该存储一个包装器对象?不,我肯定应该存储对象指针。所以我需要一些解决方案,我想这是一个常见的问题,但是很难找到正确的方法,但是如果ptr!=NULL…,这不利于代码的可读性,也不利于性能。也许你可以解释你的实际问题是什么,而不是“你是如何试图解决它的”,因为我很确定这是错误的解决方案。(哦,
dynamic_cast
通常也很慢!)不,没关系,如果ptr=NULL,即从void*获取对象的请求应该来自一个模板函数,该模板函数将指定如何获取void*的类型。在该函数中,如果ptr==NULL,我将抛出异常。几乎可以肯定,有一种比存储void*
更好的方法。如果您试图使用基于功能而非继承的多态容器,请查看基于概念的多态性。查看简要介绍和更深入的讨论。否无法使用boost::any。boost::any还需要检索存储的确切类型。所以,如果派生的ptr被存储在store.close中,我不能将其作为基类ptr检索,但不考虑继承。也就是说,如果B是从A继承的,我想从B*强制转换为A*;然后再进行容器aObj=dynamic_cast(obj);我明白了。那么我将设法提出一个更合适的解决办法。
Cast failed.
bar
bar