Почему вы используете typedef при объявлении перечисления на С++?
Я не писал ни одного С++ годами, и теперь я пытаюсь вернуться к нему. Затем я столкнулся с этим и подумал о том, чтобы отказаться:
typedef enum TokenType
{
blah1 = 0x00000000,
blah2 = 0X01000000,
blah3 = 0X02000000
} TokenType;
Что это? Почему ключевое слово typedef
используется здесь? Почему имя TokenType
появляется в этом объявлении дважды? Чем отличается семантика от этого:
enum TokenType
{
blah1 = 0x00000000,
blah2=0x01000000,
blah3=0x02000000
};
Ответы
Ответ 1
В C, объявив ваш enum, первый способ позволяет вам использовать его так:
TokenType my_type;
Если вы используете второй стиль, вам придется объявить свою переменную следующим образом:
enum TokenType my_type;
Как уже упоминалось другими, это не влияет на С++. Я предполагаю, что либо человек, который написал это, программист C в глубине души, либо вы компилируете C-код как С++. В любом случае, это не повлияет на поведение вашего кода.
Ответ 2
Это наследие 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 typedef.
Ответ 3
Вам не нужно это делать. В C (не С++) вам нужно было использовать enum Enumname для ссылки на элемент данных перечисляемого типа. Чтобы упростить его, вам было разрешено вводить его в один тип данных имени.
typedef enum MyEnum {
//...
} MyEnum;
разрешенные функции, принимающие параметр перечисления, определяемый как
void f( MyEnum x )
вместо более длинного
void f( enum MyEnum x )
Обратите внимание, что имя имени типа не обязательно должно совпадать с именем перечисления. То же самое происходит с structs.
В С++, с другой стороны, это не требуется, так как перечисления, классы и структуры могут быть доступны непосредственно как типы по их именам.
// C++
enum MyEnum {
// ...
};
void f( MyEnum x ); // Correct C++, Error in C
Ответ 4
В 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.
Ответ 5
Задержка с C.
Ответ 6
Фактический ответ на вопрос "почему" (который на удивление игнорируется существующими ответами на этот старый вопрос) заключается в том, что это объявление enum
, вероятно, находится в файле заголовка, который должен быть перекрестно скомпилирован как C и С++ (т.е. Включены в оба варианта реализации C и С++). Искусство написания таких файлов заголовков зависит от способности автора выбирать языковые функции, которые имеют надлежащее совместимое значение на обоих языках.
Ответ 7
Некоторые говорят, что у C нет пространств имен, но это неверно. Он имеет три:
-
enum
-
struct
- Глобальный (все остальное)
typedef enum { } XYZ;
объявляет анонимное перечисление и импортирует его в глобальное пространство имен с глобальным именем XYZ
.
typedef enum ABC { } XYZ;
объявляет перечисление с именем ABC
в пространстве имен enum, затем импортирует его в глобальное пространство имен как XYZ
.
enum XYZ x;
объявляет переменную типа XYZ
в пространстве имен enum.
То же самое и для пространства имен struct.
Некоторые люди не хотят беспокоиться об отдельных пространствах имен, чтобы они набирали все. Другие никогда не печатаются, потому что им требуется пространство имен.
Ответ 8
Это старый, но в любом случае, я надеюсь, вы оцените ссылку, которую я собираюсь напечатать, поскольку я оценил ее, когда встретил ее в начале этого года.
Здесь это. Я должен процитировать объяснение, которое всегда на уме, когда я должен схватить некоторые неприятные typedefs:
В объявлениях переменных введенные имена являются экземплярами соответствующих типов. [...] Однако, когда ключевое слово typedef
предшествует объявлению, введенные имена являются псевдонимами соответствующих типов
Как уже говорилось ранее, нет необходимости использовать typedefs, объявляющие перечисления в С++. Но это объяснение синтаксиса typedef! Я надеюсь, что это поможет (возможно, не OP, поскольку это было почти 10 лет, но каждый, кто пытается понять такие вещи).
Ответ 9
В некотором руководстве C codestyle версия typedef считается предпочтительной для "ясности" и "простоты".
Я не согласен, потому что typedef запутывает реальную природу объявленного объекта. На самом деле, я не использую typedefs, потому что, объявляя переменную C, я хочу быть уверенным в том, что на самом деле является объектом.
Этот выбор помогает мне быстрее запоминать то, что на самом деле делает старый кусок кода, и поможет другим при сохранении кода в будущем.