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

C++ cast void* when not sure what the type is

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

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, else 将指针 p 转换为 B* 如果它的类型是 B* 并将答案放入 b.

我尝试了 static_cast 和常规转换,但它们都在不进行运行时检查的情况下以任何方式进行转换,即使转换不正确,它们也不会抛出异常。

如果您的 class 是 多态的 那么您可以依靠 typeidtypeinfo 提供的设施(尽管您更愿意最常使用虚函数)。否则没有简单的方法可以做到这一点。

如果您想以任何方式执行此操作,则需要复制该功能。例如:-

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

然后从这个 class 派生每个 class(使用 私有继承 ),您希望在转换时确保其正确性。

如果您可以更改函数不再使用 void 指针,则可以使用某种 "safe void pointer" 替换,如下所示:

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 可能对此有一些更简洁的实现。 虽然您将需要更改所有功能,但更改本身应该很简单,甚至可以检测到您不知道的错误!

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

您可以实现自己的 RTTI。添加一个公共基础 class,这将要求其子class 报告它们的类型。然后使用 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 );
    }
}

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

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