Storing different object as void* and casting from and to void*

I am trying to store different objects in one global table with void* pointer. Problem is how to retrieve the void* object back. If I have one common base class, say Object , I can always store the void* pointer as Object and then cast back to Object*. From Object* I can cast further to the specific type.

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

I know that the solution when I have one common base class is safe, but problem is I can't have common base class, because I don't control all the different types, and can't derive them from Object. The code when I don't have common base class:

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

Questions :

Scenario 1: I store the void* pointer with the address of B ( that dynamic_cast to void* does ). then I do static_cast with A* which I know it is not safe, because I originally stored the object in the void* ptr as B*, and I know that we must store and retrieve the same type of pointer in void*. But, then I do further cast with dynamic_cast to verify that the object is actually right. so this should work, and dynamic_cast should give me the right object ?

Scenario 2: Same, but now I am fist static_casting to C*, and then further dynamic_casting , and this time I should get NULL, cause the stored object was actually B.


Storing void* is almost never necessary in C++, whereas in C it is commonplace. C++ has better, more type-safe alternatives. For example, maybe you could use Boost.Any?


As many commenters have already said, storing void* in C++ is really not necessary. If you don't have control over the types you're storing, make a container for them. That way you can control its definition and behaviour(And derive it from Object, if you wish).

Very rough working example:

#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;
}

Output:

Cast failed.
bar
bar
链接地址: http://www.djcxy.com/p/43842.html

上一篇: 静态链接与动态链接

下一篇: 将不同的对象存储为void *并将其转换为void *