当不确定类型是什么时,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 是 多态的 那么您可以依靠 typeid
和 typeinfo
提供的设施(尽管您更愿意最常使用虚函数)。否则没有简单的方法可以做到这一点。
如果您想以任何方式执行此操作,则需要复制该功能。例如:-
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 );
}
}
当我不确定另一种类型是什么时,如何在 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 是 多态的 那么您可以依靠 typeid
和 typeinfo
提供的设施(尽管您更愿意最常使用虚函数)。否则没有简单的方法可以做到这一点。
如果您想以任何方式执行此操作,则需要复制该功能。例如:-
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 );
}
}