Почему вы используете typedef при объявлении enum в C ++? - PullRequest
167 голосов
/ 22 декабря 2008

Я не писал C ++ годами и сейчас пытаюсь вернуться к нему. Затем я наткнулся на это и подумал о том, чтобы сдаться:

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

Что это? Почему здесь используется ключевое слово typedef? Почему имя TokenType дважды появляется в этой декларации? Чем семантика отличается от этой:

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

Ответы [ 9 ]

145 голосов
/ 22 декабря 2008

В C, объявление вашего enum первым способом позволяет вам использовать его так:

TokenType my_type;

Если вы используете второй стиль, вы будете вынуждены объявить свою переменную следующим образом:

enum TokenType my_type;

Как уже упоминалось, это не имеет значения в C ++. Я предполагаю, что либо человек, который написал это, в глубине души программист на C, либо вы компилируете код на C ++ В любом случае, это не повлияет на поведение вашего кода.

90 голосов
/ 22 декабря 2008

Это наследие C, в C, если вы делаете:

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

вам придется использовать его, делая что-то вроде:

enum TokenType foo;

Но если вы сделаете это:

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

Вы сможете объявить:

TokenType foo;

Но в C ++ вы можете использовать только предыдущее определение и использовать его, как если бы оно было в определении типа C.

19 голосов
/ 22 декабря 2008

Вам не нужно это делать. В C (не C ++) вы должны были использовать enum Enumname для ссылки на элемент данных перечислимого типа. Чтобы упростить его, вам было разрешено typedef использовать тип данных с одним именем.

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

разрешенные функции, принимающие параметр перечисления, должны быть определены как

void f( MyEnum x )

вместо более длинного

void f( enum MyEnum x )

Обратите внимание, что имя typename не обязательно должно совпадать с именем enum. То же самое происходит со структурами.

В C ++, с другой стороны, это не требуется, поскольку к перечислениям, классам и структурам можно обращаться напрямую как к типам по их именам.

// C++
enum MyEnum {
   // ...
};
void f( MyEnum x ); // Correct C++, Error in C
10 голосов
/ 10 февраля 2012

В C это хороший стиль, потому что вы можете изменить тип на что-то, кроме enum.

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 ++ вы можете определить enum, чтобы он компилировался как C ++ или C.

6 голосов
/ 22 декабря 2008

Удержание от C.

5 голосов
/ 27 июня 2017

Некоторые люди говорят, что в C нет пространств имен, но это технически неверно. Всего три:

  1. Теги (enum, union и struct)
  2. Метки
  3. (все остальное)

typedef enum { } XYZ; объявляет анонимное перечисление и импортирует его в глобальное пространство имен с именем XYZ.

typedef enum ABC { } XYZ; объявляет перечисление с именем ABC в пространстве имен тега, затем импортирует его в глобальное пространство имен как XYZ.

Некоторые люди не хотят беспокоиться об отдельных пространствах имен, поэтому они печатают все. Другие никогда не вводят typedef, потому что им нужно пространство имен.

3 голосов
/ 30 августа 2017

Это довольно старо, но в любом случае, я надеюсь, вы оцените ссылку, которую я собираюсь напечатать, так как я оценил ее, когда натолкнулся на нее ранее в этом году.

Здесь это . Я должен процитировать объяснение, которое всегда у меня в голове, когда я должен понять некоторые неприятные определения типа:

В объявлениях переменных введенные имена являются экземплярами соответствующих типов. [...] Однако, когда ключевое слово typedef предшествует объявлению, введенные имена являются псевдонимами соответствующих типов

Как уже говорили многие люди, нет необходимости использовать typedefs, объявляющий перечисления в C ++ . Но это объяснение синтаксиса typedef! Надеюсь, это поможет (вероятно, не ОП, поскольку прошло уже почти 10 лет, но любой, кто пытается понять подобные вещи).

1 голос
/ 18 октября 2016

Фактический ответ на вопрос «почему» (который неожиданно игнорируется существующими ответами поверх этого старого вопроса) заключается в том, что это объявление enum, вероятно, находится в заголовочном файле, который предназначен для перекрестной компиляции, так как Код на C и C ++ (т. Е. Включенный в файлы реализации C и C ++). Искусство написания таких заголовочных файлов опирается на способность автора выбирать языковые функции, которые имеют подходящее совместимое значение на обоих языках.

1 голос
/ 02 ноября 2015

В некоторых руководствах по стилю кода C версия typedef считается предпочтительной для «ясности» и «простоты». Я не согласен, потому что typedef скрывает реальную природу объявленного объекта. На самом деле, я не использую typedefs, потому что при объявлении переменной C я хочу уяснить, что на самом деле является объектом. Этот выбор помогает мне быстрее вспомнить, что на самом деле делает старый кусок кода, и поможет другим при поддержке кода в будущем.

...