当 include Windows.h 导致错误 A is not a member of B
When include Windows.h causes the error A is not a member of B
以下代码是我的包含文件:
但是,我发现当我使用#include <Windows.h>
时,项目无法编译,会报错:
"LoadImageA": is not a member of "ImageData"
这一行:
im.LoadImage("bg.png");
但是,如果我不使用#include `,一切正常。谁能帮帮我?
LoadImage 是Windows.h
里面的一个宏。它将将该文本的所有出现重写为 LoadImageW 或 LoadImageA。因此你的问题。您需要为您的资料选择不同的名称或 #undef
暂时。
这是 Win32 API 的一个常见问题,它会影响任何与支持 TCHAR
数据的 Win32 API 函数同名的符号。
在这种情况下,Windows.h
包括winuser.h
,它定义了Win32 API LoadImage()
函数如下:
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
#define
语句是导致您出现问题的原因。 #define
在范围内是全局的,不考虑文件边界、名称空间、class 定义等。它只是一个直接的文本替换。所以,当你的代码调用这个时:
im.LoadImage("bg.png");
预处理器将其更改为以下内容,这是编译器看到的内容:
im.LoadImageA("bg.png");
或:
im.LoadImageW("bg.png");
取决于您是为 MBCS 还是 Unicode 编译项目(在本例中,您使用的是 MBCS)。
如果 Microsoft 对 C++ 开发人员更好,Win32 API headers 将使用内联函数而不是 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++
这将允许对跨库、classes 等重复的任何名称进行适当的范围界定和重载。但是,遗憾的是,经过这么多年,Microsoft 似乎不愿意这样做:( Win32 API主要是为 C 和其他 C-compatible 语言设计的,它为 C++ 提供的内容非常少(不包括 GDI+、COM 等)。
无论如何,对于您的情况,最简单的解决方案是:
将 ImageData.LoadImage()
方法重命名为更独特的名称。
使用 #undef LoadImage
语句(假设您不需要在源文件的其他任何地方使用实际的 Win32 API LoadImage()
函数):
#undef LoadImage
im.LoadImage("bg.png");
或者,如果您想限制更多一点:
#ifdef _WINUSER_
#undef LoadImage
#endif
im.LoadImage("bg.png");
以下代码是我的包含文件:
但是,我发现当我使用#include <Windows.h>
时,项目无法编译,会报错:
"LoadImageA": is not a member of "ImageData"
这一行:
im.LoadImage("bg.png");
但是,如果我不使用#include `,一切正常。谁能帮帮我?
LoadImage 是Windows.h
里面的一个宏。它将将该文本的所有出现重写为 LoadImageW 或 LoadImageA。因此你的问题。您需要为您的资料选择不同的名称或 #undef
暂时。
这是 Win32 API 的一个常见问题,它会影响任何与支持 TCHAR
数据的 Win32 API 函数同名的符号。
在这种情况下,Windows.h
包括winuser.h
,它定义了Win32 API LoadImage()
函数如下:
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
#define
语句是导致您出现问题的原因。 #define
在范围内是全局的,不考虑文件边界、名称空间、class 定义等。它只是一个直接的文本替换。所以,当你的代码调用这个时:
im.LoadImage("bg.png");
预处理器将其更改为以下内容,这是编译器看到的内容:
im.LoadImageA("bg.png");
或:
im.LoadImageW("bg.png");
取决于您是为 MBCS 还是 Unicode 编译项目(在本例中,您使用的是 MBCS)。
如果 Microsoft 对 C++ 开发人员更好,Win32 API headers 将使用内联函数而不是 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++
这将允许对跨库、classes 等重复的任何名称进行适当的范围界定和重载。但是,遗憾的是,经过这么多年,Microsoft 似乎不愿意这样做:( Win32 API主要是为 C 和其他 C-compatible 语言设计的,它为 C++ 提供的内容非常少(不包括 GDI+、COM 等)。
无论如何,对于您的情况,最简单的解决方案是:
将
ImageData.LoadImage()
方法重命名为更独特的名称。使用
#undef LoadImage
语句(假设您不需要在源文件的其他任何地方使用实际的 Win32 APILoadImage()
函数):#undef LoadImage im.LoadImage("bg.png");
或者,如果您想限制更多一点:
#ifdef _WINUSER_ #undef LoadImage #endif im.LoadImage("bg.png");