203

我已经好几年没有写过任何 C++ 了,现在我正试图重新开始使用它。然后我遇到了这个并考虑放弃:

typedef enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

这是什么?为什么在typedef这里使用关键字?为什么该名称TokenType在此声明中出现两次?语义与此有何不同:

enum TokenType
{
    blah1 = 0x00000000,
    blah2=0x01000000,
    blah3=0x02000000
};
4

9 回答 9

168

在 C 中,以第一种方式声明枚举允许您像这样使用它:

TokenType my_type;

如果您使用第二种样式,您将被迫像这样声明您的变量:

enum TokenType my_type;

正如其他人所提到的,这在 C++ 中没有什么不同。我的猜测是写这篇文章的人本质上是一个 C 程序员,或者你正在将 C 代码编译为 C++。无论哪种方式,它都不会影响代码的行为。

于 2008-12-21T22:05:29.147 回答
109

It's a C heritage, in C, if you do :

enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
};

you'll have to use it doing something like :

enum TokenType foo;

But if you do this :

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

You'll be able to declare :

TokenType foo;

But in C++, you can use only the former definition and use it as if it were in a C typedef.

于 2008-12-21T22:07:02.387 回答
24

You do not need to do it. In C (not C++) you were required to use enum Enumname to refer to a data element of the enumerated type. To simplify it you were allowed to typedef it to a single name data type.

typedef enum MyEnum { 
  //...
} MyEnum;

allowed functions taking a parameter of the enum to be defined as

void f( MyEnum x )

instead of the longer

void f( enum MyEnum x )

Note that the name of the typename does not need to be equal to the name of the enum. The same happens with structs.

In C++, on the other hand, it is not required, as enums, classes and structs can be accessed directly as types by their names.

// C++
enum MyEnum {
   // ...
};
void f( MyEnum x ); // Correct C++, Error in C
于 2008-12-21T22:12:54.047 回答
12

在 C 中,这是一种很好的风格,因为您可以将类型更改为除枚举之外的其他内容。

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

foo(enum e_TokenType token);  /* this can only be passed as an enum */

foo(TokenType token); /* TokenType can be defined to something else later
                         without changing this declaration */

在 C++ 中,您可以定义枚举,以便将其编译为 C++ 或 C。

于 2012-02-10T02:08:49.660 回答
10

有人说 C 没有名称空间,但这在技术上是不正确的。它有三个:

  1. 标签(enumunionstruct
  2. 标签
  3. (其他一切)

typedef enum { } XYZ;声明一个匿名枚举并将其导入到名为 的全局命名空间中XYZ

typedef enum ABC { } XYZ;ABC声明一个在标签命名空间中命名的枚举,然后将其作为XYZ.

有些人不想打扰单独的名称空间,所以他们 typedef 一切。其他人从不 typedef 因为他们想要命名空间。

于 2017-06-27T06:08:53.920 回答
7

来自 C 的延期。

于 2008-12-21T22:03:59.260 回答
3

这有点老了,但无论如何,我希望你会喜欢我即将输入的链接,因为我在今年早些时候遇到它时很欣赏它。

这里。当我必须掌握一些讨厌的 typedef 时,我应该引用我脑海中始终存在的解释:

在变量声明中,引入的名称是相应类型的实例。[...]但是,当typedef关键字在声明之前时,引入的名称是相应类型的别名

正如许多人之前所说,没有必要在C++中使用 typedef 来声明枚举。但这就是 typedef 语法的解释!我希望它有所帮助(可能不是 OP,因为它已经快 10 年了,但是任何正在努力理解这类事情的人)。

于 2017-08-30T18:29:31.927 回答
1

“为什么”问题的实际答案(这个旧问题的现有答案令人惊讶地忽略了这个问题)是这个enum声明可能位于一个头文件中,该文件旨在作为 C 和 C++ 代码交叉编译(即包含在 C 和 C++ 实现文件中)。编写此类头文件的艺术依赖于作者选择在两种语言中具有适当兼容含义的语言特征的能力。

于 2016-10-18T15:11:39.120 回答
1

在一些 C 代码样式指南中,据说 typedef 版本是“清晰”和“简单”的首选。我不同意,因为 typedef 混淆了声明对象的真实性质。实际上,我不使用 typedef,因为在声明 C 变量时,我想清楚对象实际上是什么。这种选择有助于我自己更快地记住一段旧代码的实际作用,并在将来维护代码时帮助其他人。

于 2015-11-02T12:27:51.023 回答