当包含Windows.h导致错误A不是B的成员时

2024-05-01

以下代码是我的包含文件:

但是,我发现当我使用#include <Windows.h>,项目无法编译,会报错:

"LoadImageA": is not a member of "ImageData"

在这一行:

im.LoadImage("bg.png");

但是,如果我不使用 #include `,一切正常。谁能帮我?


这是 Win32 API 的常见问题,并且会影响与支持的 Win32 API 函数同名的任何符号TCHAR data.

在这种情况下,Windows.h包括winuser.h,它定义了 Win32 APILoadImage()函数如下:

WINUSERAPI
HANDLE
WINAPI
LoadImageA(
    __in_opt HINSTANCE hInst,
    __in LPCSTR name,
    __in UINT type,
    __in int cx,
    __in int cy,
    __in UINT fuLoad);
WINUSERAPI
HANDLE
WINAPI
LoadImageW(
    __in_opt HINSTANCE hInst,
    __in LPCWSTR name,
    __in UINT type,
    __in int cx,
    __in int cy,
    __in UINT fuLoad);
#ifdef UNICODE
#define LoadImage  LoadImageW
#else
#define LoadImage  LoadImageA
#endif // !UNICODE

The #define陈述是导致您的问题的原因。 A#define范围是全局的,不考虑文件边界、命名空间、类定义等。它只是直接的文本替换。因此,当您的代码调用此代码时:

im.LoadImage("bg.png");

预处理器将其更改为以下内容,这就是编译器所看到的:

im.LoadImageA("bg.png");

Or:

im.LoadImageW("bg.png");

取决于您是针对 MBCS 还是针对 Unicode 编译项目(在本例中,您使用的是 MBCS)。

如果 Microsoft 对 C++ 开发人员更好一点,Win32 API 标头将使用内联函数而不是 C 宏,例如:

WINUSERAPI
HANDLE
WINAPI
LoadImageA(
    __in_opt HINSTANCE hInst,
    __in LPCSTR name,
    __in UINT type,
    __in int cx,
    __in int cy,
    __in UINT fuLoad);
WINUSERAPI
HANDLE
WINAPI
LoadImageW(
    __in_opt HINSTANCE hInst,
    __in LPCWSTR name,
    __in UINT type,
    __in int cx,
    __in int cy,
    __in UINT fuLoad);

#ifdef __cplusplus
inline HANDLE LoadImage(
    __in_opt HINSTANCE hInst,
    __in LPCTSTR name,
    __in UINT type,
    __in int cx,
    __in int cy,
    __in UINT fuLoad)
{
  #ifdef UNICODE
  return LoadImageW(hInst, name, type, cx, cy, fuLoad);
  #else
  return LoadImageA(hInst, name, type, cx, cy, fuLoad);
  #endif // !UNICODE
}
#else
  #ifdef UNICODE
  #define LoadImage  LoadImageW
  #else
  #define LoadImage  LoadImageA
  #endif // !UNICODE
#endif // !C++

这将允许对跨库、类等重复的任何名称进行适当的作用域和重载。但是,唉,这么多年过去了,微软似乎不愿意这样做:( Win32 API 主要是为 C 和其他 C 兼容语言设计的,它提供了对于 C++ 的规定非常少(不包括 GDI+、COM 等)。

无论如何,根据您的情况,最简单的解决方案是:

  1. 重命名ImageData.LoadImage()方法给一个更独特的名字。

  2. use an #undef LoadImage声明(假设您不需要使用实际的 Win32 APILoadImage()在源文件中的其他位置运行):

    #undef LoadImage
    im.LoadImage("bg.png");
    

    或者,如果您想限制更多一些:

    #ifdef _WINUSER_
    #undef LoadImage
    #endif
    
    im.LoadImage("bg.png");
    
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当包含Windows.h导致错误A不是B的成员时 的相关文章

随机推荐