当我不确定其他类型是什么时,如何将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和常规强制转换,但是它们都没有进行运行时检查,并且即使转换不正确,也不会抛出异常。
答案 0 :(得分:1)
如果您的课程是多态,那么您可以依靠typeid
和typeinfo
提供的工具(尽管您最常使用虚拟功能)。否则,没有简单的方法可以做到这一点。
如果您想要这样做,那么您需要复制该功能。例如: -
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 );
}
}