是否可以使用方法返回使用#define创建的变量?

时间:2015-03-05 16:33:41

标签: c++ winapi win32gui

想象一下我有代码:

#define ID_BUTTON 1

为了给自己一个变量,以便在使用CreateWindow()函数创建按钮时使用。

现在,我可以使用方法返回ID_BUTTON吗?通常我会发现它相对容易,但我不知道我必须指定哪种函数类型。

所以,

1)有可能吗?

2)如果是这样,我必须使用哪种功能类型?

请记住它只是简单的代码,如:

<function_type> getID() {
return ID_BUTTON;
}

谢谢,

2 个答案:

答案 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

甚至:

#defineconstconstexprenum语句不会创建变量;他们创建 cconstants 。变量和常量都是标识符,它们引用程序中的值。不同之处在于常量不能在运行时更改,而变量可以。

但是,

#define不会创建任何普通常量。它实际上告诉编译器的一部分名为预处理器,使用字符串ID_BUTTON实际替换源代码中的文本1。这可能很有用,这就是你 为C做的事情,但在C ++中,constexpr(在C ++ 11中引入)通常更优。请参阅Christian Hackl的答案。

如果您要使用常量将值传递给API,这是您计划对ID_BUTTON执行的操作,那么API通常会告诉您它所期望的类型,因此您可以使用该类型而不是让编译器确定作业的最佳类型。但是,请参阅下面关于Windows中控件标识符的讨论,因为ID_BUTTON的具体情况有一个问题。

如果你控制了这种类型,你将不得不更多地考虑使用什么类型。在某些情况下,语言的类型提升规则可以让你在没有类型的情况下说出1,但如果你要创建已知的小整数或大整数,或位字段或浮点数,那么你'我需要使用适当的类型名称或限定符(shortlongunsignedfloatdouble等。需要一点时间来弄清楚要去哪里,但是一旦你完成它就足够自然了。


假设您不了解Windows中控件标识符的工作原理:

采用控件标识符的大多数API函数(例如GetDlgItem())将控件标识符作为int;因此,您的控件标识符应具有类型int

但是,CreateWindow()CreateWindowEx()期望控件标识符为倒数第三个参数。此参数的类型为HMENU。 C ++不允许您将int推送到HMENU,因此您必须使用强制转换:(HMENU) ID_BUTTON。 (可能有一个等效的C ++风格的演员,但我不知道/忘记它是什么。)

此外,如果您要使用资源文件,则必须使用#define语句创建ID_xxx常量名称作为资源文件格式没有constconstexprenum。在这种情况下,继续使用#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_BUTTONIDOK冲突。 (例如,如果它们发生冲突,您会看到奇怪的事情,例如控件激活对话框管理器知道的键盘快捷键。)此问题的规范解决方案是开始在100对控件标识符进行编号(我相信Visual Studio对此负责,但我不确定。)