С++: что означает "static enum"
Я недавно наткнулся на это:
static enum Response{
NO_ERROR=0,
MISSING_DESCRIPTOR,
...
};
Он компилируется и работает под MSVS2005. Однако я не уверен, что должен делать "статический" модификатор. Разве это не отличается от следующего?
enum Response {
NO_ERROR=0,
MISSING_DESCRIPTOR,
...
};
Ответы
Ответ 1
Этот точный код с удаленным многоточием недействителен С++. Вы не можете использовать спецификатор класса static
в объявлении enum
; это не имеет никакого смысла (только объекты, функции и анонимные объединения могут быть объявлены static
).
Вы можете, однако, объявить enum
и переменную все в одном объявлении:
static enum Response {
NO_ERROR = 0,
MISSING_DESCRIPTOR
} x;
static
здесь относится к x
, и это фактически так же, как если бы вы сказали:
enum Response {
NO_ERROR = 0,
MISSING_DESCRIPTOR
};
static Response x;
Ответ 2
Удивительно, что вы также можете добавить туда других спецификаторов decl.
Это компилируется в VS2008:
auto const enum TestEnum {
Why,
Does
};
register volatile enum TestEnum2 {
This,
Work
};
Но это не имеет никакого смысла:)
Я подозреваю, что проблема заключается в разборе, потому что такой код выглядит следующим образом:
enum TestEnum3 { Hello, World }; // Define enum
enum TestEnum3 x = World; // Use enum
Также может быть записано как:
enum TestEnum3 { Hello, World } x = World; // Define and use enum.
Интересно, что я замечаю, что вы делаете это в VS2008:
enum TestEnum3 { Hello, World };
const enum TestEnum3 e3 = World;
const enum TestEnum4 { F, M, L } e4 = F;
e3 = Hello; // error C2166: l-value specifies const object (Good!)
e4 = M; // NO ERROR here though - why?
Таким образом, они не эквивалентны, как в случае с TestEnum4
, это, похоже, выбрасывает спецификатор объявления const
. Все очень странно.
Ответ 3
static enum Response { /*... */ };
Вы не можете определить static
enum в С++. static
может быть только переменной перечисления, а не самого типа!
Компиляция вашего кода с помощью GCC
version 4.3.4
, он дает эту ошибку:
prog.cpp: 7: ошибка: класс хранения может только для объектов и Функции
Посмотрите себя онлайн на ideone: http://www.ideone.com/cI1bt
Я думаю, что все это говорит.
-
Однако, если вы хотите ограничить тип enum Response
в своей собственной единицы перевода, вы можете использовать неназванное пространство имен. Взгляните на эту тему:
Превосходство неназванного пространства имен по статическому?
Ответ 4
Стандартный
С++ 11 N3337 стандартный проект. Приложение C 7.1.1 говорит, что оно разрешено на C, но не имело эффекта и стало незаконно в С++:
Изменить: в С++ статические или внешние спецификации могут применяться только к именам объектов или функций. Использование этих спецификаторов с объявлениями типов является незаконным в С++. В C эти спецификаторы игнорируются при использовании на объявления типов. Пример:
static struct S { // valid C, invalid in C++
int i;
};
Обоснование: Спецификаторы класса хранения не имеют никакого значения при привязке к типу. В С++ класс члены могут быть объявлены с помощью спецификатора класса статического хранилища. Разрешение спецификаторов класса хранения по типу объявления могут сделать код запутанным для пользователей.
И как struct
, enum
также является объявлением типа.
Обоснование реализации
Определения Enum не имеют хранилища и не создают символов в объектных файлах, таких как переменные и функции. Просто попробуйте выполнить компиляцию и декомпиляцию:
struct S { int i; int j; };
int i;
с:
g++ -c main.c
nm main.o
и вы увидите, что символ S
отсутствует, но есть символ i
.
Когда компилятор видит значения перечисления, он просто вставляет его буквально в скомпилированный код. Это только работает, конечно, потому что они являются константами времени компиляции.
Поэтому они должны быть включены в файлы заголовков.
См. также:
Ответ 5
В С#:
";" является необязательным для обратной совместимости после блока перечисления. Он не допускает такую семантику на этом языке для именованных типов. статические, общественные и т.д. Пространство имен не может содержать элементы, такие как поля или методы.
Требуется тег:
ArgTypes var = ArgTypes.CUT;
В C/С++:
Требуется ';' в конце блока перечисления.
Для глобальных переменных пространства имен, перечислений и т.д. Статический по умолчанию.
int type;
typedef enum {
TOKENIZE,
CUT
} ArgTypes;
type = TOKENIZE; /* <ArgTypes>::TOKENIZE */
type = ArgTypes::CUT;
// Recommended Use
enum ArgTypes {
TOKENIZE,
CUT
}; /* Same as above */
enum Test {
TOKENIZE,
CUT
} ArgTypes;
type = ArgTypes::TOKENIZE;
type = CUT; /* Assign type => <Test>.CUT */
type = Test::CUT;
enum {
TOKENIZE,
CUT
} ArgTypes; /* Unamed.. requires tag */
type = TOKENIZE; /* <unamed>.TOKENIZE=0 => #define TOKENIZE 0*/
type = ArgTypes::TOKENIZE; /* ** ERROR ** */
Ответ 6
Я не уверен, почему статичность была использована или почему она даже компилируется. Должно просто быть перечисление ответа.
Перечислители не являются статическими данными.