如何获取 void* 指针的 typeid?
Posted
技术标签:
【中文标题】如何获取 void* 指针的 typeid?【英文标题】:How to get the typeid of a void* pointer? 【发布时间】:2011-07-04 13:30:27 【问题描述】:我有一个指向对象的指针列表。这些对象没有任何共同点(即没有共同的基类);为了更好地理解:它是位于 GUI 中鼠标光标下的对象列表。
现在我想知道它是什么类型的对象。一个节点、一个节点句柄、一条线段、一个标签等等。但是我不能使用typeid(*ptr)
,因为ptr 是const void*
。
有什么解决办法吗?我可以强制使用 typeid 吗,因为我知道指针总是指向对象而不是单纯的值?还是没有办法添加一些假的通用基类?
(编辑:目前我这样做是在列表中存储一个结构,该结构另外存储对象的类型(作为枚举)。也许我应该将其更改为存储 type_info
对象... )
【问题讨论】:
给他们一个通用的基类,并使用它。typeid
用于多态类型,而不是 void*
。
为什么是假的通用基类?如果列表中的每个对象“都是”ObjectLyingUnderTheMouse,那么这不是假的,那么 ObjectLyingUnderTheMouse 是有意义的。如果没有,那就是糟糕的设计,请更改设计。尤其是当您在对象中混合视图和模型时。
@larsm:也许是因为问题是“”,而不是“请告诉我如何重新设计我的代码”;-)
@simon:您要求进行反思,这是 C++ 所没有的。但是,您的陈述“这些对象没有共同点”是不正确的。您自己说过:它们是“位于 GUI 中鼠标光标下的对象”。这些对象在在您的设计中没有任何共同点,而您需要反思来解决这种缺乏共性的问题,这是对您设计的反思。
@all 感谢您的提示。你是对的——我现在稍微改变了设计并添加了一个公共基类。
【参考方案1】:
对于技术解决方案,不考虑设计级别,当然在用户开始使用鼠标之前,使用std::map
或哈希表(无论如何)将非类型化指针与类型描述符或类型化指针相关联。
在更高的层次上,void* 指针只是不好的。
最好修复设计,而不是使用像std::map
这样的杂牌。
干杯&hth。
【讨论】:
【参考方案2】:您绝对应该引入多态虚拟基类或此目的。否则,您需要先对另一个可能不相关的指针类型执行reinterpret_cast/static_cast
,以便能够调用dynamic_cast
。由于在 C++ 中访问具有错误类型的对象是未定义的,因此使用 dynamic_cast
会触发未定义的行为。
从技术上讲,RTTI 信息通常存储在对象的 vtable 字段中,因此劫持二进制表示可能会起作用,并为您提供每个类型的唯一指针。请不要那样做。
【讨论】:
……啊……删除了我要评论的部分……:) @Nim:对不起,我正在编辑,我在改写了一下后重新介绍了该部分。 在转换之后我总是从 typeid 得到转换类型,不管它之前是什么对象。奇怪……不过,我现在决定添加一个通用的基类。【参考方案3】:您应该考虑使用 boost::variant 类型来保存原始指针(在将它们转换为 void* 之前),并将它们存储在您的列表中。
然后,您可以尝试使用 Get 成员函数直接检索您的指针,或者更好的是,如果您有多个可能的类型要在同一点处理,则使用访问者语法。
【讨论】:
【参考方案4】:声明并定义一个名为“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
;
然后将您的void*
替换为列表中的Object
。
每次迭代这个列表,首先调用Object
类的GetType
函数,知道这个Object
的void指针指向的对象的类型。 GetType
将此类型的名称返回为const char*
字符串。
您可以使用strcmp
函数来帮助您比较const char*
字符串。
然后你调用GetType
函数,现在你知道将Object
的void指针转换或转换为哪种类型,然后对当前迭代对象做任何你想做的事!
调用GetPointer
函数的两个重载之一来检索Object
的空指针是否已转换/强制转换。
如果你只想引用Object
的void指针指向的对象,那么只需调用GetReference
函数而不是GetPointer
。
希望你喜欢我的回答!
【讨论】:
以上是关于如何获取 void* 指针的 typeid?的主要内容,如果未能解决你的问题,请参考以下文章