我是一名java开发人员,但最近我不得不学习C++,我对一些事情感到困惑。我想做的是创建一个"全局"头文件,其中有一个#define变量列表,这些变量将在我创建的套件中保持不变。我创建了头文件,并添加了一些变量
#ifndef CONSTANTS_H
#define CONSTANTS_H
#define SM_START 1001;
#define SM_PAUSE 1002;
#define SM_STOP 1003;
#define SM_SAVE 1004;
#define SM_DISCARD 1005;
#define SM_SETUP 1007;
#endif // CONSTANTS_H
我的问题是我无法访问这些。。。
我已经在需要的地方包含了头文件,但我无法访问其中的常量。我是否有一个.cpp文件?有没有一种方法可以让我访问常量变量?
首先:不应该将分号放在#define
的末尾。#define
是一个预处理器指令,这意味着它基本上用内容替换定义的名称。因此,如果您执行类似于int a = SM_STOP + 1;
的操作,则会使用您的代码将其预处理为int a = 1003; + 1;
,这不是您想要的。
第二:标头本身通常不编译,而仅用于包含在*.cpp
文件或其他标头中(其中#include
再次是文本替换)。因此,是的,你需要在某个地方有一个.cpp
文件(不完全是这样,首先你可以选择不同的扩展名,其次你甚至可以给编译器一个头作为编译单元,但我建议不要这样做,至少在你知道自己在做什么之前)。但是,您不需要为常量设置.cpp
文件,只需将头#include
放入您想在.中使用常量的任何文件中即可
第三:为什么在这里使用预处理器定义?这似乎是枚举的完美工作。然后,您可以将其放入名称空间/结构中,以消除对它们加前缀的需要(使用SM_
)。或者,您可以只使用C++11的新enum class
,它的行为与java的枚举非常相似。我会尽可能避免使用预处理器。因为它只是文本替换,而且不尊重任何作用域等等,所以很容易遇到问题(比如分号)。
问题是在#define
之后有分号。这是唯一阻止你使用"常数"的东西,从技术上讲,这些常数不是常数;它们是预处理器定义。
从逻辑上讲,C++编译器通过预处理器运行程序的文本,预处理器是一个执行从#
开始的指令的文本过滤器。#define
指令指示预处理器查找其左侧部分的所有出现,并将其逐字替换为右侧部分。在您的情况下,它包含分号,从而导致替换后的表达式无效。
例如,
if (command == SM_DISCARD) ...
成为
if (command == 1005;) ...
这是一个错误,编译器将其报告为无效语法。
使用#include <constants.h>
或任何文件名来包含此文件。此外,您不需要分号#defines是编译器对代码进行的文本替换。
您不需要cpp
文件。包括页眉就足够了。
预处理器用后面的任何东西扩展你的定义。
SM_START
将变为1001;
所以一个像这样的表达式
int x = SM_START;
将转换为
int x = 1001;;
这仍然是合法的。
但这个分号可能会导致类似的问题
int x = SM_START * 10;
将扩展为:
int x = 1001; * 10;
这显然是非法的。
此外,预处理器指令不能与全局指令混淆。尽管您可能不应该使用全局变量,但使用#defines
可能比定义class Global
或仅使用分组在namespace
中的变量更糟糕。