How to get the typeid of a void* pointer?
I have a list of pointers to objects. These objects 开发者_Python百科have nothing in common (i.e. no common base class); for better understanding: It is a list of objects that lie under the mouse cursor in a GUI.
Now I would like to know what kind of object it is. A node, a node handle, a line segment, a tag, and so on. However I cannot use typeid(*ptr)
since ptr is a const void*
.
Any solution for this? Can I force the usage of typeid since I know that the pointers always point to objects and not to mere values? Or is there no way around adding some fake common base class?
(edit: Currently I'm doing it that way that I store a struct in the list which additionally stores the type of the object (as enum). Maybe I should change this to store a type_info
object ...)
For a technical solution, not considering design level, use a std::map
or hash table (whatever) to associate the untyped pointers with type descriptors or typed pointers, of course before the user starts using the mouse.
At a higher level, the void* pointers are just ungood.
It would be best to fix the design instead of employing a kludge like the std::map
.
Cheers & hth.
You definitely should introduce a polymorphic dummy base class or this purpose. Otherwise, you would need to do a reinterpret_cast/static_cast
to another, possibly unrelated pointer type first in order to be able to call dynamic_cast
. Since accessing an object with its wrong type is undefined in C++, such a use of dynamic_cast
would trigger undefined behaviour.
Technically, RTTI information is typically stored in a field of an object's vtable, so hijacking the binary representation might just work and give you an per-type unique pointer. Please don't do that.
You should consider using the boost::variant type to hold your raw pointers (before you convert them to void*), and store those in your list instead.
You can then either attempt to retrieve your pointers back directly using the Get member function, or better yet, if you have multiple possible types to deal with at the same point, using the visitor syntax.
Declare and define a new class named "Object":
class Object
{
private: const void *pointer
const char *type;
public: template <class T> Object(const T *t)
{
this->pointer = t;
this->type = typeid(*t).name();
//NOTE that you must #include <typeinfo.h> in order to use the "typeid" keyword of course!
}
const void* GetPointer()
{
return this->pointer;
}
const char* GetType()
{
return this->type;
}
template <class T> const T* GetPointer()
{
return (T*)this->pointer;
}
template <class T> T& GetReference()
{
return *(T*)this->pointer;
}
template <class T> T GetValue()
{
return *(T*)this->pointer;
}
//You also can add some explicit and/or implicit conversions operators if you want by using template class in each
};
Then replace your void*
with Object
in your list.
Each time you iterate this list, first call the GetType
function of the Object
class to know the type of the object that the void pointer of this Object
points at. GetType
returns the name of this type as const char*
string.
You can use the strcmp
function to help you compare const char*
strings.
Then after that you called GetType
function, now you know to which type to convert or cast the void pointer of the Object
and then do whatever you want with the current iterated object!
Call one of the two overloads of the GetPointer
function to retrieve the void pointer of the Object
converted / casted or not.
If you just want the reference to the object that the void pointer of the Object
points at, then just call the GetReference
function instead GetPointer
.
Hope if you like my answer!
精彩评论