Reputation: 757
how can I cast void* to another type in C++, when I'm not sure what the other type is. this is a sample of my code:
class A
{
};
class B
{
};
void main()
{
void * p;
if (rand() % 2)
p = new A();
else
p = new B();
A * a = NULL;
B * b = NULL;
}
I want a code to cast the pointer p to A* if its type is A* and put the answer in a, else cast the pointer p to B* if its type is B* and put the answer in b.
I tried static_cast and regular cast, but they both cast any way without making runtime check, and even if the cast is not correct, they don't throw an exception.
Upvotes: 1
Views: 210
Reputation: 13354
You can implement your own RTTI. Add a common base class which will require its subclasses to report their types. Then use static_cast to get the actual type.
#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 );
}
}
Second option is to keep the type information outside the classes, like this:
#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 );
}
}
Upvotes: 0
Reputation: 10733
If your classes are polymorphic then you can rest on facility provided by typeid
and typeinfo
(Although you'd rather use virtual functions most often). Otherwise there's no easy way to do this.
If any way you want to do it then you need to replicate that functionality. For e.g:-
template<typename T>
class TypeStoringBase
{
private:
enum Type { CLASS_A, CLASS_B, CLASS_C ...};
protected:
~TypeStoringBase();
public:
...
};
And then derive every class from this class (using private inheritance )for which you want to ensure correctness while casting.
Upvotes: 1
Reputation: 21803
If you can change the functions not to use void pointers any more, you can use some kind of "safe void pointer" replacement, along the following lines:
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 may have some perhaps tidier implementation of this. Although you will need to change all your functions, the change itself should be straightforward, and may even detect bugs you didn't know about!
Note that this solution makes no assumptions about the underlying types. They don't need to have virtual functions or be copyable.
Upvotes: 1