如何获取 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?的主要内容,如果未能解决你的问题,请参考以下文章

C++:如何获取浮点指针的地址并将其转换为 void**

显示来自通用指针的值

typeid详解

将 void* 转换为动态类型

指向对象开头的指针 (C++)

jquery 如何获取从客户端传递过来参数的值(typeId,tableCode,empCode)