【发布时间】:2014-09-13 10:42:43
【问题描述】:
我必须在 C++11 中为 HFONT、HWND、HMODULE 等 Win32 句柄编写一个引用计数包装类。我想使用一个隐式转换为所有句柄类型(都是 void* typedef)的单个 WinHandle 类。不幸的是,所有句柄都有不同的函数来销毁底层对象,例如 DestroyWindow()、CloseHandle()、DeleteObject() 等等,因此我需要为每个句柄类型使用不同的类来实现适当的销毁函数。 (那将是 47 个类 + 基类,包括用户对象、gdi 对象和内核对象)
那么有没有办法在运行时确定句柄是哪个“类型”,或者更确切地说,需要调用哪个函数? (在文档中我只找到了 isWindow() 函数)
我已经考虑过使用 RTTI 或调用所有删除函数,直到其中一个成功。 RTTI 不起作用,因为所有 HANDLE 类型都是 void* 的类型定义,因此是相同的。后者可能有效,但所有句柄必须是唯一的才能正常工作(任何 GDI 句柄都不能与用户句柄或内核句柄具有相同的值),否则可能会导致错误和内存泄漏
【问题讨论】:
-
句柄不一定是
void *typedef。我相信是STRICT给了他们自己的类型(并且有充分的理由)。 -
这些关闭/删除函数中的很多/大多数(全部?)不是采用
HANDLE并返回BOOL吗?如果是这样,您可以将删除函数作为BOOL (*deleter)(HANDLE)传递给句柄包装器的构造函数,将其存储在您的包装器对象中并在适当时调用它。 -
NtQueryObject 可能会帮助你,但如果我没记错的话,不要使用 USER 或 GDI 句柄。
-
即使有这样的检测功能,也无济于事。假设
IsWindow()和IsFont()都返回TRUE。 (这是可能的,因为唯一的保证是没有两个窗口具有相同的句柄,但一个窗口句柄可能等于一个字体句柄。)您仍然不知道您是否有一个窗口句柄或一个字体句柄。你需要知道你有什么样的手柄。 (STRICT宏可能会有所帮助。) -
您可能需要
WinHandle<HFONT>、WinHandle<HWND>等。但是您为什么需要引用计数的包装器?已经有DuplicateHandle。