想象一下我有代码:
#define ID_BUTTON 1
为了给自己一个变量,以便在使用CreateWindow()
函数创建按钮时使用。
现在,我可以使用方法返回ID_BUTTON吗?通常我会发现它相对容易,但我不知道我必须指定哪种函数类型。
所以,
1)有可能吗?
2)如果是这样,我必须使用哪种功能类型?
请记住它只是简单的代码,如:
<function_type> getID() {
return ID_BUTTON;
}
谢谢,
杰
答案 0 :(得分:1)
从技术上讲,使用C ++ 11 decltype
:
#define ID_BUTTON 1
auto getID() -> decltype(ID_BUTTON)
{
return ID_BUTTON;
}
int main()
{
auto x = getID();
}
在那里,无需为int
或函数指定ID_BUTTON
。
但问题的真正答案应该是:不要将宏用于常量。 C ++有const
(以及最近的)constexpr
这一点。
答案 1 :(得分:0)
假设你不明白什么
#define ID_BUTTON 1
甚至:
#define
,const
,constexpr
和enum
语句不会创建变量;他们创建 cconstants 。变量和常量都是标识符,它们引用程序中的值。不同之处在于常量不能在运行时更改,而变量可以。
#define
不会创建任何普通常量。它实际上告诉编译器的一部分名为预处理器,使用字符串ID_BUTTON
实际替换源代码中的文本1
。这可能很有用,这就是你 为C做的事情,但在C ++中,constexpr
(在C ++ 11中引入)通常更优。请参阅Christian Hackl的答案。
如果您要使用常量将值传递给API,这是您计划对ID_BUTTON
执行的操作,那么API通常会告诉您它所期望的类型,因此您可以使用该类型而不是让编译器确定作业的最佳类型。但是,请参阅下面关于Windows中控件标识符的讨论,因为ID_BUTTON
的具体情况有一个问题。
如果你控制了这种类型,你将不得不更多地考虑使用什么类型。在某些情况下,语言的类型提升规则可以让你在没有类型的情况下说出1
,但如果你要创建已知的小整数或大整数,或位字段或浮点数,那么你'我需要使用适当的类型名称或限定符(short
,long
,unsigned
,float
,double
等。需要一点时间来弄清楚要去哪里,但是一旦你完成它就足够自然了。
假设您不了解Windows中控件标识符的工作原理:
采用控件标识符的大多数API函数(例如GetDlgItem()
)将控件标识符作为int
;因此,您的控件标识符应具有类型int
。
但是,CreateWindow()
和CreateWindowEx()
期望控件标识符为倒数第三个参数。此参数的类型为HMENU
。 C ++不允许您将int
推送到HMENU
,因此您必须使用强制转换:(HMENU) ID_BUTTON
。 (可能有一个等效的C ++风格的演员,但我不知道/忘记它是什么。)
此外,如果您要使用资源文件,则必须使用#define
语句创建ID_xxx
常量名称作为资源文件格式没有const
,constexpr
或enum
。在这种情况下,继续使用#define
作为标识符,将这些#define
推送到自己的包含文件中,并将#include
来自C ++源代码和资源文件。{/ p >
如果您不使用资源文件,则根本不必担心使用控件标识符;只需直接使用HWND
为每个控件。您仍应分配控件标识符,以防您在窗口中需要选项卡导航或其他对话框消息处理,但除此之外,您可以直接使用HWND
。 (我忘记了控制标识符是否包含在标签导航中。)
最后,有许多预定义的控件标识符对对话管理器具有特殊含义。这是来自微软的winuser.h:
/*
* Dialog Box Command IDs
*/
#define IDOK 1
#define IDCANCEL 2
#define IDABORT 3
#define IDRETRY 4
#define IDIGNORE 5
#define IDYES 6
#define IDNO 7
#if(WINVER >= 0x0400)
#define IDCLOSE 8
#define IDHELP 9
#endif /* WINVER >= 0x0400 */
您自己的控件标识符应避免与这些标识符冲突;您的ID_BUTTON
与IDOK
冲突。 (例如,如果它们发生冲突,您会看到奇怪的事情,例如控件激活对话框管理器知道的键盘快捷键。)此问题的规范解决方案是开始在100
对控件标识符进行编号(我相信Visual Studio对此负责,但我不确定。)