当不确定类型是什么时,C ++ cast void *

时间:2015-01-12 14:02:28

标签: c++ casting void-pointers

当我不确定其他类型是什么时,如何将void *转换为C ++中的另一个类型。 这是我的代码示例:

class A
{
};
class B
{
};
void main()
{
    void * p;
    if (rand() % 2)
        p = new A();
    else
        p = new B();

    A * a = NULL;
    B * b = NULL;
}

我想要一个代码将指针p转换为A *,如果它的类型是A *并将答案放在a中, 如果其类型为B *,则将指针p转换为B *并将答案放入b。

我尝试了static_cast和常规强制转换,但是它们都没有进行运行时检查,并且即使转换不正确,也不会抛出异常。

3 个答案:

答案 0 :(得分:1)

如果您的课程是多态,那么您可以依靠typeidtypeinfo提供的工具(尽管您最常使用虚拟功能)。否则,没有简单的方法可以做到这一点。

如果您想要这样做,那么您需要复制该功能。例如: -

template<typename T>
class TypeStoringBase
{
  private:
    enum Type { CLASS_A, CLASS_B, CLASS_C ...};
  protected:
    ~TypeStoringBase();
  public:
    ...
};

然后从此类中派生每个类(使用私有继承),以便在投射时确保正确性。

答案 1 :(得分:1)

如果你可以改变函数不再使用void指针,你可以使用某种&#34;安全无效指针&#34;更换,顺序如下:

struct A{};
struct B{};

struct AnyBase
{
    virtual ~AnyBase() = 0;
};
inline AnyBase::~AnyBase() {}

template<class T>
struct Any : public AnyBase
{
    Any(T *p) : p(p) {}
    T *p;
};

void MaybeA(const AnyBase& p1)
{
    const Any<A> *p2 = dynamic_cast<const Any<A>*>(&p1);
    if (p2)
    {
        A *pa = p2->p;
        cout << "Is an A\n";
    }
    else
    {
        cout << "Is not A\n";
    }
}

int main()
{
    A a;
    B b;
    MaybeA(Any<A>(&a));
    MaybeA(Any<B>(&b));
}

Boost可能会有一些更整洁的实现。 虽然您需要更改所有功能,但更改本身应该很简单,甚至可能检测到您不了解的错误!

请注意,此解决方案不会对基础类型做出任何假设。他们不需要具有虚拟功能或可复制。

答案 2 :(得分:0)

您可以实施自己的RTTI。添加一个公共基类,它将要求其子类报告其类型。然后使用static_cast获取实际类型。

#include <stdlib.h>


enum class Type { A, B };

class Base {
public:
    virtual Type type() const = 0;
    virtual ~Base() {}
};

class A : public Base
{
    Type type() const { return Type::A; }
};
class B : public Base
{
    Type type() const { return Type::B; }
};

int main()
{
    void * p;
    if (rand() % 2)
        p = new A();
    else
        p = new B();

    Base *base = static_cast<Base*>( p );

    A * a = NULL;
    B * b = NULL;

    if ( base->type() == Type::A ) {
        a = static_cast<A*>( base );
    } else if ( base->type() == Type::B ) {
        b = static_cast<B*>( base );
    }
}

第二个选项是将类型信息保留在类之外,如下所示:

#include <stdlib.h>

class A
{
};
class B
{
};
int main()
{
    void * p;
    bool is_a;

    if (rand() % 2) {
        p = new A();
        is_a = true;
    } else {
        p = new B();
        is_a = false;
    }

    A * a = NULL;
    B * b = NULL;

    if ( is_a ) {
        a = static_cast<A*>( p );
    } else {
        b = static_cast<B*>( p );
    }
}