我需要将指针转换为 long (SendMessage()),并且我想安全地检查另一侧的变量是否正确。所以我正在考虑做 dynamic_cast 但这不适用于非虚拟的类。然后我想到了做 typeid 但这将工作,直到我将派生的 var 作为它的基础。
有什么方法可以检查指针是否是我在运行时所期望的?有没有办法我可以使用 typeid 来查看指针是否是从特定基派生的类型?
您提到的SendMessage()
使我听起来像 MS Windows 是您的平台,然后建议阅读使用指针的规则 (Windows) 。它详细介绍了Microsoft 在此类情况下为您提供的功能和其他内容PtrToLong
。PtrToUlong
如果你只有一个long
,那么你真的无能为力。没有通用的方法来确定任意数字是否代表有效的内存地址。即使你知道它是一个有效的内存地址,也没有办法确定指针指向的东西的类型。如果在它的地址被转换为之前你不能确定事物的真实类型long
,那么你就不能确定将它转换为long
你计划转换为的任何类型是安全的。
您只需要相信消息的发件人已向您发送了一个有效值。您能做的最好的事情是采取一些预防措施,以减少您自己的程序收到虚假值时的后果。
您不能使用 typeid。如果您得到垃圾而不是有效指针,它将导致访问冲突,因此您的检查是无意义的。
您应该做的是将您的 SendMessage 和处理消息的代码包装到一个类型安全的接口中。这样,您将无法将意外的东西传递给 SendMessage,并且不需要对接收方进行任何检查。
C++ 类型系统在编译时工作。一旦将指针转换为 long,就会丢失所有类型信息。long 只是内存中的很多位。您无法确定它指向一个对象。
PTLib ( http://sourceforge.net/projects/opalvoip/ ) 使用 PCLASSINFO 宏来定义类之间的关系。这提供了 IsDescendant 和 GetClass 等函数。
您可能可以实现类似的东西。
dynamic_cast 通过检查虚拟方法表的签名来工作。如果你没有虚拟方法,你就没有 VMT,所以正如你所说的 dynamic_cast 将不起作用。但是,如果您没有 VMT,则您绝对不知道所指向的对象。
您最好的选择是要求指针指向具有至少一个虚拟方法的类,即使它是一个虚拟方法。动态转换将起作用。
我还不明白你的问题是关于什么的。
UINT_PTR
。因此,您确实UINT_PTR v = reinterpret_cast<UINT_PTR>(ptr);
要转换为整数类型,然后执行相反的操作以再次将其转换回指针。C++ 标准保证恢复原始值。(有关我对此的解释,请参见我上面给出的链接)。顺便说一下,那个微软网站还说 WPARAM 和 LPARAM 会根据平台改变它们的大小。所以你可以只使用那个变量v
和SendMessage
它。在 Windows 中,MFC 提供了一种方法来检查给定的指针是否指向有效的内存位置(这是通过捕获 segfault 来完成的)。我不记得函数名,但它在那里。尽管如此,它并不能确保指向的内存内容是有效的。它可能仍然有无效的 VMT 并使您的代码崩溃。当然,您可以自己捕获段错误(请参阅 MS 知识库)
至于检查某物是否属于一种类型,您必须从一个基类开始。如果将基类的析构函数设为“虚拟”,则所有派生类都将具有 VMT。
如果您必须不惜一切代价避免 VMT,则必须有某种标识符来告诉您正在处理的内容,例如 MS Windows 事件中的事件类型。