将不同的对象存储为void *并将其转换为void *

我试图用void *指针在一个全局表中存储不同的对象。 问题是如何检索void *对象。 如果我有一个公共基类,比如Object,我总是可以将void *指针存储为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 * does)。 然后我用A *做static_cast,我知道它是不安全的,因为我最初将对象存储在void * ptr中作为B *,并且我知道我们必须在void *中存储和检索相同类型的指针。 但是,然后我进一步使用dynamic_cast进行投射来验证对象是否正确。 所以这应该工作,dynamic_cast应该给我正确的对象?

场景2:同样的,但现在我首先static_casting到C *,然后进一步dynamic_casting,这次我应该得到NULL,导致存储的对象实际上是B.


存储void *在C ++中几乎不是必需的,而在C中它是司空见惯的。 C ++有更好的,更安全的选择。 例如,也许你可以使用Boost.Any?


正如许多评论者已经说过的那样,在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
链接地址: http://www.djcxy.com/p/43841.html

上一篇: Storing different object as void* and casting from and to void*

下一篇: Passing arbitrary data to a function without void pointers