使用枚举或#define?

时间:2010-03-30 20:32:42

标签: c++

我正在构建一个玩具解释器,并且我已经实现了一个包含令牌类型和值的令牌类。

令牌类型通常是整数,但我应该如何抽象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
};

9 个答案:

答案 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
  • 创建自己的类是最好的选择,例如,你可以在这里获得漂亮的打印信息,但这也是一项工作(不多,但仍然如此)。

此外,intenum方法可能会生成与#define方法一样高效的代码:只要有可能,编译器会将const值替换为实际值。

答案 3 :(得分:1)

在你所描述的情况下,我更喜欢使用enum,因为它们更容易维护。特别是,如果数字表示没有任何特定的含义。

答案 4 :(得分:1)

Enum是类型安全的,更易于阅读,更易于调试并且受到intellisense的良好支持。我会说尽可能使用Enum,并在必要时使用#define。

在C / C ++中查看关于const与define的相关讨论,当你必须使用#define预处理器时,我对这篇文章的回答也列出了。

Shall I prefer constants over defines?

答案 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。
  • 更改基础类型:您可以更改其基础类型(许多编译器也提供扩展以在C ++ 98中执行此操作):enum class Color : unsigned short。 unsigned short将是类型。
  • 显式范围(我最喜欢的):在上面的示例中,Red将是未定义的;你必须使用Color::Red。想象一下新的枚举也是一种命名空间,所以它们不会污染你当前的命名空间,可能是一个常见的名称(“红色”,“有效”,“无效”,e tc)。
  • 前向声明enum class Color;告诉编译器Color是一个枚举,您可以开始使用它(当然不是值);有点像class Test;,然后使用Test *