我正在构建一个玩具解释器,并且我已经实现了一个包含令牌类型和值的令牌类。
令牌类型通常是整数,但我应该如何抽象int?
什么是更好的主意:
// #defines
#define T_NEWLINE 1
#define T_STRING 2
#define T_BLAH 3
/**
* Or...
*/
// enum
enum TokenTypes
{
t_newline = 1,
t_string = 2,
t_blah = 3
};
答案 0 :(得分:15)
枚举可以投入到整数中;此外,它们是枚举 C ++中预定义值列表的首选方式。与#define
不同,它们可以放在名称空间,类等中。
此外,如果您需要以1开头的第一个索引,则可以使用:
enum TokenTypes
{
t_newline = 1,
t_string,
t_blah
};
答案 1 :(得分:4)
Enums在调试器中工作(例如,说“print x”将打印“English”值)。 #defines没有(即你留下数字并且必须自己引用来源进行映射)。
因此,请使用枚举。
答案 2 :(得分:3)
这里有各种解决方案。
首先,使用#define
指的是C
的旧时代。它通常被认为是C++
中的不良做法,因为以这种方式定义的符号不遵守范围规则,而是由不执行任何语法检查的预处理器替换......导致难以理解的错误。
其他解决方案是关于创建全局常量。净效益是,不是由预处理器解释,它们将由编译器解释,因此遵守语法检查和范围规则。
有很多方法可以创建全局常量:
// ints
const int T_NEWLINE = 1;
struct Tokens { static const int T_FOO = 2; };
// enums
enum { T_BAR = 3; }; // anonymous enum
enum Token { T_BLAH = 4; }; // named enum
// Strong Typing
BOOST_STRONG_TYPEDEF(int, Token);
const Token NewLine = 1;
const Token Foo = 2;
// Other Strong Typing
class Token
{
public:
static const Token NewLine; // defined to Token("NewLine")
static const Token Foo; // defined to Token("Foo")
bool operator<(Token rhs) const { return mValue < rhs.mValue; }
bool operator==(Token rhs) const { return mValue == rhs.mValue; }
bool operator!=(Token rhs) const { return mValue != rhs.mValue; }
friend std::string toString(Token t) { return t.mValue; } // for printing
private:
explicit Token(const char* value);
const char* mValue;
};
所有人都有自己的优点和缺点。
int
缺乏类型安全性,您可以轻松地在另一个预期的地方使用一类常量enum
支持自动递增,但你没有漂亮的打印,它仍然不是那么类型安全(即使有点好)。StrongTypedef
我更喜欢enum
。您可以返回int
。此外,int
和enum
方法可能会生成与#define
方法一样高效的代码:只要有可能,编译器会将const值替换为实际值。
答案 3 :(得分:1)
在你所描述的情况下,我更喜欢使用enum,因为它们更容易维护。特别是,如果数字表示没有任何特定的含义。
答案 4 :(得分:1)
Enum是类型安全的,更易于阅读,更易于调试并且受到intellisense的良好支持。我会说尽可能使用Enum,并在必要时使用#define。
在C / C ++中查看关于const与define的相关讨论,当你必须使用#define预处理器时,我对这篇文章的回答也列出了。
答案 5 :(得分:0)
我投票给枚举
#define
不是类型安全的,如果你不小心可以重新定义。
答案 6 :(得分:0)
枚举的另一个原因:它们是作用域的,所以如果标签 t_blah 出现在另一个名称空间(例如另一个类)中,它不会干扰 t_blah 您当前的命名空间(或类),即使它们具有不同的int表示形式。
答案 7 :(得分:0)
enum
提供了类型安全性和可读性以及调试器。如前所述,它们非常重要。
枚举提供的另一件事是可能性的集合。 E.g。
enum color
{
red,
green,
blue,
unknown
};
我认为#define
(或const
就此问题无法做到这一点)
答案 8 :(得分:0)
好的,已经发布了很多答案,所以我会想出一些不同的东西:C++0x强类型的枚举器:)
enum class Color /* Note the "class" */
{
Red,
Blue,
Yellow
};
int color = Color::Red;
将是编译时错误。您必须使用Color color
或将Red转换为int。enum class Color : unsigned short
。 unsigned short将是类型。Red
将是未定义的;你必须使用Color::Red
。想象一下新的枚举也是一种命名空间,所以它们不会污染你当前的命名空间,可能是一个常见的名称(“红色”,“有效”,“无效”,e tc)。enum class Color;
告诉编译器Color
是一个枚举,您可以开始使用它(当然不是值);有点像class Test;
,然后使用Test *
。