我正在使用LPARAM
(基本上是long
,除非我们在64位系统上,在这种情况下它是long long
)成员{{1} }(称为LVITEM
)存储指向与lParam
中的条目重合的对象的指针。
当我想编辑该项目时,我想将ListView
强制转换为LPARAM
,只要MyClass*
正确设置为等于{lParam
,该工作正常首先是{1}},但我想做某种检查确保实际上是这个数字指向的MyClass*
。< / p>
目前我有这个:
MyClass
现在,我并不完全清楚:如果参数不是有效指针,LVITEM lv;
// lv is filled in by LVM_GETITEM
classPtr = static_cast<MyClass*>((void*)lv.lParam);
if ( !classPtr )
return false;
会返回static_cast
吗?我假设没有,因为那是NULL
的用途,但我并不完全确定。并且,如果我在这个假设中是正确的,那么在我尝试访问其成员并导致崩溃之前,有没有办法检查dynamic_cast
是否有效......
答案 0 :(得分:5)
static_cast<>
不会对类型执行运行时检查,因此您所拥有的内容将无法工作,至少不会像您认为的那样。所有static_cast<>
都是基于编译时已知的信息的指针算法。
dynamic_cast<>
可能工作,但它要求该类至少有一个虚拟函数(对于RTTI),如果LPARAM
不是,它肯定会失败。甚至是指向类类型的指针。
在给定任意指针或整数值(如LPARAM
)的情况下,没有一般方法可以确定它实际指向MyClass
的实例。
在特定情况下我会做的是将列表视图包装在自己的类中,并公开仅适用于MyClass
的方法。可能是这样的:
class MyListView
{
public:
MyListView() { /* create the list view HWND */ }
~MyListView() { /* destroy the list view HWND */ }
void Add(MyClass* listItem) // Only way to add items to list view
{
// Add to list view
}
MyClass* Get() const
{
LVITEM lv;
// lv is filled in by LVM_GETITEM
// Assume that this will work, since the only way to add
// list view items is through Add(), and Add() only accepts
// an instance of MyClass. Therefore the list view will only
// have pointers to instances of MyClass.
return static_cast<MyClass*>((void*)lv.lParam);
}
// ...
private:
// Set to private so users can't modify
// the list view without our consent.
HWND listView;
};
这种方法的优点是,现在您可以完全控制列表视图控件及其界面,因此这将始终有效(尽管存在错误和恶意/无能的程序员)。您甚至可以将其设为模板,以便它适用于MyClass
以外的类。
答案 1 :(得分:3)
您无法在纯标准C ++中查看它。您只能使用Windows API进行概率检查。因此,在实践中,您只能通过使代码正确来保证它。
如果你可以检查它,你仍然不知道它是 正确的MyClass
实例。
因此,唯一的好方法是保证代码正确无误。当您限制对事物的访问时,这会更容易。 C ++有许多功能可以帮助您限制访问,例如const
;使用它们。
干杯&amp;第h。,
答案 2 :(得分:2)
如果LPARAM
不是MyClass
类型的指针,而是任意位模式,则static_cast
和dynamic_cast
都将显示未定义的行为。如果指向有效对象的指针被强制转换为不相关的类,dynamic_cast
将返回NULL
,但它不支持检查特定内存中是否存在有效的多态对象位置。
除了维护MyClass*
对象的有效指针的全局列表之外,没有智能的方法来检查这一点。
答案 3 :(得分:1)
几乎没有办法找出答案。你必须为所有对象创建一些父对象(让我们称之为grand_dad),然后从中继承所有对象。然后使用更改LPARAM到grand_dad*
并使用dynamic_cast<MyClass*>(lv.lparam)
。
关于动态和静态演员的一点注意事项:
答案 4 :(得分:0)
无需崩溃。在Windows中,使用structured exception handling。
您还可以将LONG magic_number设为MyClass的第一个字段,并将其视为额外的保险,即它不是其他对象。
答案 5 :(得分:0)
到目前为止,最简单的解决方案是保留列表ov有效MyClass
个对象。在每个ctor中,将this
添加到列表中;在析构函数中,您将其从列表中删除。
这并不能保护您免受巧合,但即便如此,您也有一个有效的MyClass*
。它甚至涵盖了派生类,因为它们确实调用了基础构造函数。