C++ 将不同的对象存储为void*并在void之间进行转换*

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

我试图用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
类对象{};
类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