0

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

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

4

7 回答 7

3

您提到的SendMessage()使我听起来像 MS Windows 是您的平台,然后建议阅读使用指针的规则 (Windows) 。它详细介绍了Microsoft 在此类情况下为您提供的功能和其他内容PtrToLongPtrToUlong

于 2008-11-22T22:17:29.760 回答
1

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

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

于 2008-11-22T20:51:16.333 回答
1

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

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

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

于 2008-11-22T22:00:57.690 回答
0

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

您可能可以实现类似的东西。

于 2008-11-22T20:37:03.117 回答
0

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

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

于 2008-11-22T20:37:33.350 回答
0

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

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

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

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

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

于 2008-11-24T18:53:33.510 回答