当包含Windows.h导致错误A不是B的成员 [英] When include Windows.h causes the error A is not a member of B
问题描述
以下代码是我的包含文件:
The following code are my include files:
但是,我发现当我使用 #include< Windows.h>
时,项目无法编译,会出现错误:
However, I find that when I use #include <Windows.h>
, the project can not compile, it will come with an error:
"LoadImageA": is not a member of "ImageData"
在这一行:
im.LoadImage("bg.png");
但是,如果我不使用#include`,一切正常。任何人都可以帮助我吗?
However, if I do not use #include `, everything works fine. Can any one help me?
推荐答案
这是Win32 API的常见问题,会影响任何具有相同名称的符号作为支持 TCHAR
数据的Win32 API函数。
This is a common problem with the Win32 API, and affects any symbols that have the same name as Win32 API functions that support TCHAR
data.
在这种情况下, Windows.h
包含 winuser.h
,它定义了Win32 API LoadImage()
函数,如下所示:
In this case, Windows.h
includes winuser.h
, which defines the Win32 API LoadImage()
function as follows:
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
在范围内是全局的,并不尊重文件边界,名称空间,类定义等。它只是一个直接的文本替换。所以,当你的代码调用它时:
The #define
statements are what is causing your problem. A #define
is global in scope, and doesn't respect file boundaries, namespaces, class definitions, etc. It is just a straight text replacement. So, while your code is calling this:
im.LoadImage("bg.png");
预处理器将其更改为以下内容,这是编译器看到的内容:
The preprocessor changes it to the following, which is what the compiler sees:
im.LoadImageA("bg.png");
或者:
im.LoadImageW("bg.png");
取决于您是为MBCS还是Unicode编译项目(在这种情况下,您使用的是MBCS) )。
Depending on whether you are compiling your project for MBCS or Unicode (in this case, you are using MBCS).
如果微软对C ++开发人员更好,Win32 API头文件将使用内联函数而不是C宏,例如:
If Microsoft would be nicer to C++ developers, the Win32 API headers would use inline functions instead of C macros, eg:
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等)。
That would allow proper scoping and overloading of any names repeated across libraries, classes, etc. But alas, Microsoft seems unwilling to do that after all these years :( The Win32 API is primarily designed for C and other C-compatible languages, it provides very little provisions for C++ (not counting things like GDI+, COM, etc).
在任何情况下,对于您的情况,最简单的解决方案是:
In any case, for your situation, the simplest solution is to either:
-
将
ImageData.LoadImage()
方法重命名为更独特的名称。
rename the
ImageData.LoadImage()
method to a more unique name.
使用 #undef LoadImage
语句(假设您不需要使用实际的Win32 API LoadImage()
函数源文件中的任何其他位置):
use an #undef LoadImage
statement (assuming you don't need to use the actual Win32 API LoadImage()
function anywhere else in your source file):
#undef LoadImage
im.LoadImage("bg.png");
或者,如果你想要更具限制性:
Or, if you want to be a little more restrictive:
#ifdef _WINUSER_
#undef LoadImage
#endif
im.LoadImage("bg.png");
这篇关于当包含Windows.h导致错误A不是B的成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!