【问题标题】:check if X is derived of Y via typeid检查 X 是否通过 typeid 从 Y 派生
【发布时间】:2008-11-22 20:20:49
【问题描述】:

我需要将指针转换为 long (SendMessage()) 我想安全地检查另一边的变量是否正确。所以我正在考虑做 dynamic_cast 但这不适用于非虚拟的类。然后我想到了做 typeid ,但是直到我传递一个派生的 var 作为它的基础。

有什么方法可以检查指针是否是我在运行时所期望的? 有没有办法可以使用 typeid 来查看指针是否是从特定基派生的类型?

【问题讨论】:

  • 您的问题文本与您的问题标题有何关联?
  • 我认为它展示了糟糕的设计。如果绝对不涉及虚函数,为什么需要知道基类?这不像你可以安全地沮丧或任何事情。另外,在编写基类时最好至少有一个虚拟 dtor。
  • 这不是与stackoverflow.com/questions/311102/… 几乎相同的问题,但建议的方法不同吗?

标签: c++ casting typeid


【解决方案1】:

您对SendMessage() 的引用使我听起来像MS Windows 是您的平台,然后推荐阅读Rules for Using Pointers (Windows)。它详细介绍了 PtrToLongPtrToUlong 函数以及 Microsoft 在此类情况下为您提供的其他内容。

【讨论】:

    【解决方案2】:

    如果您只有long,那么您无能为力。没有通用的方法来确定任意数字是否代表有效的内存地址。即使您知道它是一个有效的内存地址,也无法确定指针指向的事物的类型。如果在地址转换为 long 之前您无法确定事物的真实类型,那么您无法确定将 long 转换为您计划转换的任何类型是否安全它到。

    您只需要相信邮件的发件人已向您发送了一个有效值。您能做的最好的事情就是采取一些预防措施,以减少您自己的程序收到虚假值时的后果。

    【讨论】:

      【解决方案3】:

      您不能使用 typeid。如果您得到垃圾而不是有效指针,则会导致访问冲突,因此您的检查是无意义的。

      您应该做的是将您的 SendMessage 和处理消息的代码包装到一个类型安全的接口中。这样,您将无法将意外的东西传递给 SendMessage,并且不需要在接收方进行任何检查。

      C++ 类型系统在编译时工作。一旦将指针转换为 long,就会丢失所有类型信息。 long 只是内存中的很多位。您无法确定它指向一个对象。

      【讨论】:

        【解决方案4】:

        PTLib (http://sourceforge.net/projects/opalvoip/) 使用 PCLASSINFO 宏来定义类之间的关系。这提供了 IsDescendant 和 GetClass 等函数。

        你也许可以实现类似的东西。

        【讨论】:

          【解决方案5】:

          dynamic_cast 通过检查虚拟方法表的签名来工作。如果你没有虚拟方法,你就没有 VMT,所以正如你所说的 dynamic_cast 将不起作用。但是,如果您没有 VMT,则您绝对不知道所指向的对象。

          最好的办法是要求指针指向具有至少一个虚拟方法的类,即使它是一个虚拟方法。动态转换将起作用。

          【讨论】:

            【解决方案6】:

            我还不明白你的问题是什么。

            • 如果您是否可以确定转换为 long 和 back 将产生相同的值,请查看 Safely checking the type of a variable
              鉴于另一个应答器链接到的“使用指针的规则”MS-Site,正确的类型转换为UINT_PTR。因此,您执行 UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr); 将其转换为整数类型,然后执行相反的操作以再次将其转换回指针。 C++ 标准保证恢复原始值。 (有关我对此的解释,请参阅我上面给出的链接)。顺便说一句,那个微软网站还说 WPARAM 和 LPARAM 会根据平台改变它们的大小。因此,您可以使用该变量 vSendMessage 它。
            • 如果你可以在另一边检查指针(转换为某种指针类型)是否指向某个对象,答案是你不能。由于您显然不确定用于发送它的指针类型,因此您无法在接收端检查指针指向的动态类型是什么。如果您知道指针在发送方的类型,则一开始就不需要您的检查。

            【讨论】:

              【解决方案7】:

              在 Windows 中,MFC 提供了一种方法来检查给定的指针是否指向有效的内存位置(这是通过捕获 segfault 来完成的)。我不记得函数名称,但它就在那里。尽管如此,它并不能确保指向的内存内容是有效的。它可能仍然有无效的 VMT 并使您的代码崩溃。当然,你可以自己捕获段错误(see MS Knowledge Base

              至于检查某个东西是否属于一个类型,你必须从一个基类开始。如果将基类的析构函数设为“虚拟”,则所有派生类都将具有 VMT。

              如果您必须不惜一切代价避免 VMT,则必须有某种标识符来告诉您正在处理的内容,例如 MS Windows 事件中的事件类型。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-09-06
                • 2018-05-20
                • 2016-07-22
                • 1970-01-01
                • 2022-01-08
                • 2020-09-19
                相关资源
                最近更新 更多