Windows句柄的获取器

3
我已经学习C++几个月了,最近在我的IDE(Jetbrains CLion FTW!)中遇到了一个奇怪的问题。
我的IDE可以为成员生成getter,自动确定类型、是否为const以及其他关键字。显然,生成并不完美,所以我通常不使用这个功能。目前我正在专注于Windows API,需要处理句柄。所以当我为句柄(HINSTANCE、HWND、HDC等)生成getter时,会发生一些非常奇怪的事情。
假设我有一个如下定义的成员:
HDC m_hDeviceContext;

那么当我的IDE生成一个getter时,它看起来像这样:

const HDC__* getDeviceContext() const...

我很困惑为什么类型是HDC__。它被声明为指针,因此在winnt.h中,句柄被声明为指针(typedef struct name##__ *name)。

有人能给我解释一下为什么会出现这种情况吗?这是我的IDE的bug吗?因为每当我看到返回句柄的getter的示例时,它们通常只返回直接的句柄类型。


看起来是你的IDE出了问题,或者可能是某个设置有误。或者至少是一个设计缺陷(如果不是设置的问题)。 - user253751
你可能是对的,CLion相当新。它应该生成什么? - oliveryas01
3
当然,我希望它生成“HDC getDeviceContext() const {return m_hDeviceContext;}”。 - user253751
那样更有意义,谢谢。 - oliveryas01
1个回答

4

HDC被定义为一个不透明的struct指针的typedef

typedef const struct HDC__ *HDC;

或者在旧的Windows版本中作为从DECLARE_HANDLE(HDC)扩展的虚拟类型:

typedef struct HDC__{int i;}*HDC;

这个定义的目的是为了防止不同类型的句柄被 typedefWORDLONG 或者 DWORD 而变成相同的整数。将它们作为指向不同结构体的指针可以防止在出现不匹配时编译。微软公司至少已经使用这种方法20年了。
您的集成开发环境可能会查看调试信息而不是解析头文件,并且不会撤销 typedef 的效果。
在 C++ 中,struct 标签在当前命名空间中隐式地被 typedef。因此,struct HDC__ 同样创建了类型 HDC__。由于某种原因,您的 IDE 假定了这一点。如果您正在作为 C++ 进行编译,则没有问题。如果您正在作为 C 进行编译,那么就很遗憾了,这个错误可能只是您遇到的最小问题之一。

我认为它并没有查看调试信息,可能只是在扩展typedef。 - Matteo Italia
我很好奇为什么他们定义了这个结构。指向不完整类型的指针是一个更严格的实体。你甚至不能将零添加到这样的指针中。 - Minor Threat
你也不能隐式地将一个指向不完整类型的指针转换为另一个指针。比如,如果 HDC__ 和 HBRUSH__ 是不完整类型,那么 DHC__* 就不能被转换为 HBRUSH__*。 - Minor Threat
@MinorThreat:这正是我写的。很久以前,句柄只是被定义为WORDtypedef。很容易混淆,传递错误类型的句柄不会被编译器检测到。这些不透明的结构体typedef是避免愚蠢错误的重大改进。 - chqrlie
不,WORD 的 typedef 不是不完整类型。不完整类型是指前向声明但未定义的结构体。你可以有一个指向这样的 struct 的指针,但除了将其存储在变量中或将其传递给外部 API 外,无法对其进行任何操作。甚至不能将字面零添加到这样的指针中。这是句柄的理想解决方案。但 HDC__ 不是不完整类型。它是一个没有成员的完整 struct 类型。也许微软忽视了这种可能性,我不知道。或者我说的是旧版 <windows.h>。有一段时间没看过了。 - Minor Threat
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接