【问题标题】:Forward declare HINSTANCE and friends转发声明 HINSTANCE 和朋友们
【发布时间】:2011-02-04 04:43:28
【问题描述】:

有没有办法从 WinAPI 前向声明 HINSTANCE 类型而不包括完整(和大)windows.h 标头?

例如,如果我有一个拥有HINSTANCE mInstance 的类RenderWindow,我将不得不在RenderWindow.h 中包含windows.h。所以所有需要RenderWindow的东西也必须包括windows.h

我尝试包含windef.h,但这似乎需要windows.h 的一些东西。 :-(如果我不能转发声明它,是否至少有一种可移植的方式在RenderWindow中使用long mInstance之类的东西而不是HINSTANCE

【问题讨论】:

  • 包含 windows.h 是否真的会给您带来任何问题?
  • 不是直接的,但我不喜欢包含它,因为有时必须取消定义 minmax 宏,我认为它会增加编译时间/查找等。
  • #define NOMINMAX 之前包括<windows.h>
  • 我可以想出六个很好的理由来避免包含它。 min/max,常用名称的宏(例如 CreateWindow),以及它不能编译为 C++ 的事实。您必须启用 Microsoft 的语言扩展。 windows.h 在各方面都表现不佳。
  • 对于那些登陆这里寻找用 C 指针类型 void * 替换 HINSTANCE 的人(我现在放弃)有一个 heated discussion about its opacity

标签: c++ winapi hinstance


【解决方案1】:

HINSTANCE 在 WinDef.h 中声明为 typedef HINSTANCE__* HINSTANCE;

你可以在标题中写:

#ifndef _WINDEF_
class HINSTANCE__; // Forward or never
typedef HINSTANCE__* HINSTANCE;
#endif

如果不包含 WinDef.h,您将收到引用 HINSTANCE 的编译错误。

【讨论】:

  • 这就是我正在寻找的黑客,非常聪明! (HINSTANCE__ 在 MSVC2005 上似乎是 struct
  • 这不是 hack,Windef.h 被写入允许它 :-) 如果稍后包含 Windef.h,则声明一个类而不是结构会保证编译器错误,这意味着错误的文件结构设计。
  • 我明白了,但是如果我使用类,如果我稍后在我的实现文件中包含windows.h,我会得到一个编译器错误,其中我需要windows.h。建议在头文件中使用 typedef 并在相应的源文件中包含 windows.h 是不是文件结构不好?
  • 如果您在 this 编译单元中需要 Windows.h,请先将其作为其他库头文件包含在您自己的头文件之前。
  • 对不起,tumbleweed 这个,但我在使用它时遇到了问题(并且需要它!) - 我正在尝试在 *nix 上编译一些 C 代码。使用这个出色的解决方案会导致error: unknown type name 'class'。我的 C 很差:\ @AlainRist
【解决方案2】:

您可以将其声明为 void* 并将错误丢弃。不过,这接近于一场永无止境的战斗,迟早你会被绊倒。使用预编译的头文件,这样你就不用关心 windows.h 的大小了

stdafx.h:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

【讨论】:

    【解决方案3】:

    例如,如果我有一个拥有HINSTANCE mInstance 的类RenderWindow,我将不得不在RenderWindow.h 中包含windows.h。所以所有需要RenderWindow的东西也必须包括windows.h

    你看过Pimpl idiom吗?这允许您隐藏私人成员。副作用是您不必将它们的标题包含在类的标题中。

    【讨论】:

    • 是的,Pimpl 是我通常这样做的方式。
    • 感谢您的建议。我从来没有少说我更喜欢 Alain Rist 的解决方案。
    【解决方案4】:

    嘿@NoSenseEtAl 我猜我们还在那里。

    在 2021 年,HINSTANCE&lt;minwindef.h&gt; 中定义。直接包含&lt;minwindef.h&gt; 会报错:“No Target Architecture”

    要解决该错误,请执行以下操作(假设为 x64 构建):

    #define _AMD64_
    #include <minwindef.h>
    
    int main() {
        HINSTANCE h;
    }
    

    请注意,宏 _AMD64_ 没有文档记录,它以下划线开头,因此不能由用户定义。

    并且它仅由&lt;Windows.h&gt; 定义,因此没有更小的标题可以包含使其定义。

    显然,Windows SDK 与 Modules 一起工作的希望更大,因此可以改为通过 Modules 来修复构建速度。

    【讨论】:

      【解决方案5】:

      处理不包含标头的句柄的最佳可移植方式是reinterpret_cast将它们转换为大小完全相同的类型。

      大多数句柄都有指针大小1。所以void*uintptr_t 可以。例子:

      • _beginthreadexuintptr_t 而不是 HANDLE 返回到线程。
      • MSVC thread::native_handle 返回void*

      请务必在您看到字体的地方static_assert 了解字体大小。

      1 几个句柄没有指针大小,我只记得AcquireCredentialsHandle返回的那个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多