Объявление, определение и использование перечислителя
Как известно, в языке C/C++ можно использовать#defineиconstдля создания символьных констант, а использованиеenumинструмент может не только создавать символьные константы, но и определять новые типы данных, однако это нужно делать по определённым правилам. Давайте рассмотримenumи его использование.
Шаг (1) — объявление и определение перечислителей
(1) Сначала рассмотрим следующую инструкцию:
enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};
Эта инструкция выполняет две функции:
- Первое: оно объявляет enumType как новый тип данных, называемый перечислением;
- Второе: оно объявляет Monday, Tuesday и т. д. как символьные константы, обычно называемые перечислителями, значения по умолчанию которых равны соответственно 0-6. (Как явно инициализировать значения перечислителей, мы расскажем позже.)
(2)Затем используйте новый перечисляемый тип enumType для объявления переменных этого типа: enumType Weekday, так же как при объявлении переменной с базовым типом int, например int a; вы также можете определять переменные перечисления при определении типа перечисления.
enum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}Weekday;
Однако, в отличие от базовых типов переменных, без приведения типа вы можете присваивать переменной этого перечисляемого типа только определённые элементы перечисления. Например: Weekday = Monday; или Weekday = Sunday; Вы не можете присваивать другие значения переменной перечисления, например Weekday = 10; Это не разрешено, потому что 10 не является элементом перечисления. Иными словами, Weekday может быть только одним из определённых элементов перечисления Monday-Sunday. Но это не абсолютно; в шестом пункте будет рассмотрено использование приведения типа для присваивания переменным перечисления значений других типов.
(3)Выше было сказано, что значения, не являющиеся элементами перечисления, нельзя присваивать переменным перечисления. Тогда можно ли присваивать элементы перечисления переменным, не являющимся перечислениями? Например:int a=Monday;Это разрешено, потому что элементы перечисления являются символическими константами. При этом присваивании компилятор автоматически преобразует элемент перечисления в тип int.
(4)Ранее мы говорили, что над перечислениями можно выполнять операции присваивания. Могут ли переменные перечисления участвовать в арифметических операциях?
Weekday++;Weekday = Monday + Tuesday;
Это недопустимо, потому что такие операции могут привести к нарушению ограничений типа. Например:
Weekday = Sunday; Weekday++;
Сначала Weekday присваивается последнее значение элемента перечисления Sunday (значение 6). Если продолжить инкрементировать, Weekday увеличится до 7, но 7 недопустимо для типа enumType.
Итог:Для перечислений определён только оператор присваивания; арифметические операции для перечислений не определены.
(5)Над элементами перечисления нельзя выполнять арифметические операции. Тогда могут ли элементы перечисления участвовать в операциях с переменными других типов?
int a; a = 1 + Monday;
Это разрешено, потому что компилятор автоматически преобразует элементы перечисления в тип int.
(6)Во втором пункте говорилось: без приведения типа переменной этого типа перечисления можно присваивать только определённые перечислители. Отсюда следует, что значения других типов можно присваивать переменным перечисления с помощью приведения типа:
Weekday = enumType(2);
Эквивалентно:
Weekday = Wednesday;Но что произойдёт, если вы попытаетесь присвоить переменной перечисления через приведение типа значение, выходящее за пределы диапазона значений перечисления?
Weekday = enumType(20);
Результат будет неопределённым. Это не вызовет ошибки, но вы не получите желаемого результата.
Шаг (2) — Настройка значений перечислителей
(1)Ранее мы говорили об определенииenum enumType {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};Перечислители Monday, Tuesday и т. д. по умолчанию имеют значения 0-6 соответственно. Мы можем явно задать значения перечислителей:
enum enumType {Monday=1, Tuesday=2, Wednesday=3, Thursday=4, Friday=5, Saturday=6, Sunday=7};
Указанные значения должны быть целыми числами!
(2)Также можно явно определить только некоторые из значений перечислителей:
enum enumType {Monday=1, Tuesday, Wednesday=1, Thursday, Friday, Saturday, Sunday}; Таким образом, и Monday, и Wednesday определены как 1, поэтому Tuesday=2, а значения по умолчанию для Thursday, Friday, Saturday и Sunday равны 2, 3, 4, 5 соответственно.
Итог:Значение неинициализированного перечислителя по умолчанию на 1 больше значения предыдущего перечислителя.
(3)Второй пункт также иллюстрирует ещё одно явление: значения перечислителей могут совпадать.
Шаг (3) — Диапазон значений перечисления
Ранее упоминалось, что значения других типов можно присваивать переменным перечисления с помощью приведения типа:
Weekday = enumType(2);
Это допустимо;
Но
Weekday = enumType(20);
недопустимо. Здесь затрагивается понятие диапазона значений перечисления: верхняя граница перечисления — это наименьшая степень числа 2, которая больше максимального перечислителя, минус 1;
Нижняя граница перечисления имеет два случая: 1. Если минимальное значение перечислителя не меньше 0, нижняя граница равна 0; 2. Если минимальное значение перечислителя меньше 0, нижняя граница — это наибольшая степень числа 2, которая меньше минимального перечислителя, плюс 1.
Например:
Предположим, мы определяемenum enumType1 { First=-5,Second=14,Third=10 };Тогда верхняя граница перечисления равна 16-1=15 (16 больше максимального перечислителя 14 и является степенью числа 2); нижняя граница равна -8+1=-7 (-8 меньше минимального перечислителя -5 и является степенью числа 2).
Шаг (4) — Применения перечислений
Лично я считаю, что enum и switch — лучшие партнёры:
enum enumType{Step0, Step1, Step2}Step=Step0; // 注意这里在声明枚举的时候直接定义了枚举变量 Step,并初始化为 Step0
switch (Step)x
{
case Step0:{...;break;}
case Step1:{...;break;}
case Step2:{...;break;}
default:break;
}
Кроме того, существует редкий вариант использования enum, который представляет собойenum { one ,two ,three};то есть без указания имени. В этом случае мы, естественно, не можем определять типы перечислений. При этом это эквивалентноstatic const int one = 0;определяя таким образом три константы. Тогда при использовании вы простоint no = one。
Строго типизированные перечисления
1. Краткое описание
Строго типизированные перечисления, также известные как enum classes, — это новый синтаксис в C++11, используемый для решения недостатков традиционных типов перечислений C++. В традиционном C++ константы перечисления видны во внешней области видимости, поэтому если в одной и той же области видимости есть два разных типа перечислений, они не могут содержать одну и ту же константу перечисления. Например:
enum Side{Right,Left};
enum Thing{Wrong,Right};
Их нельзя использовать вместе.
Ещё один недостаток заключается в том, что традиционные значения перечислений всегда неявно преобразуются в целые числа, а пользователи не могут определить базовый тип. Строго типизированные перечисления в C++11 решают эти проблемы.
2. Строго типизированные перечисления
Строго типизированные перечисления объявляются с использованием синтаксиса `enum class` следующим образом:
enum class Enumeration{
VAL1,
VAL2,
VAL3=100,
VAL4
};
Таким образом, тип перечисления безопасен, и значения перечислителей не будут неявно преобразовываться в целые числа, а также их нельзя сравнивать с целочисленными значениями. Например (`Enumeration::VAL4 == 10` вызовет ошибку компиляции).
Кроме того, базовый тип, используемый перечислением, по умолчанию — `int`, но можно указать и другие типы, например:
enum class Enum:unsigned int{VAL1,VAL2};
Как упоминалось ранее, строго типизированные перечисления позволяют решить проблему традиционных перечислений, когда одинаковые имена перечислителей встречаются в разных классах перечислений. При использовании перечислителя типа перечисления необходимо указывать его область видимости, например: `Enum::VAL1`, тогда как `VAL1` сам по себе больше не имеет значения.
Ещё один момент, который стоит отметить: предварительное объявление типов перечислений также возможно в C++11, например:
enum class Enum; enum class Enum1:unsigned int;
3. Фрагменты кода строго типизированных перечислений в проектах
1. Обработка изображений
enum class Color{RED,BLUE,YELLOR,BLACK,WHITE};
2. Светофоры
enum class TrafficLight{RED,YELLOR,GREEN};
Строго типизированные перечислители обладают функциональностью традиционных перечислений — именованием значений перечислителей — а также имеют классоподобные характеристики: у них есть члены с областью видимости класса, и они не могут подвергаться преобразованию типов по умолчанию. Поэтому их также называют классами перечислений — `enum class`.
Базовый тип данных класса перечисления должен быть знаковым или беззнаковым целочисленным типом, например `char`, `unsigned int`, `unsigned long`; по умолчанию используется `int`.
3. Применение предварительного объявления
enmu class Clolor:char; //前置声明枚举类
void Foo(Color*p); //前置声明的使用
//....................
enum class Color:char{RED,GREEN,BLACK,WHITE}; //前置声明的定义
Ссылка: http://blog.csdn.net/u012333003/article/details/20612267