Я новичок в программировании на C ++.
Сегодня наткнулся на новую тему: строго типизированный enum
. Я немного исследовал это, но до сих пор не могу понять, зачем нам это нужно и что от этого нужно?
Например, если у нас есть:
enum xyz{a, b, c};
/*a = 0, b = 1, c = 2, (Typical C format)*/
Зачем нужно писать:
enum class xyz{a, b, c};
Что мы здесь пытаемся сделать? Мое самое главное сомнение - как им пользоваться. Не могли бы вы привести небольшой пример, который поможет мне понять.
enum class Colours
иenum class Fruits
. Потому что, когда я писал код в VS 2010. Он выдает ошибку"expects a defination or a tag name"
подclass
.На этой странице IBM есть хорошая статья о перечислениях , она очень подробная и хорошо написана. Вот некоторые важные моменты вкратце:
Перечисления с ограниченной областью видимости устраняют большинство ограничений, налагаемых обычными перечислениями: полная безопасность типа, четко определенный базовый тип, проблемы с областью видимости и предварительное объявление.
источник
Значения
enum class
действительно имеют типenum class
,underlying_type
а не C-перечисления.enum xyz { a, b, c}; enum class xyz_c { d, f, e }; void f(xyz x) { } void f_c(xyz_c x) { } // OK. f(0); // OK for C++03 and C++11. f(a); // OK with C++11. f(xyz::a); // ERROR. f_c(0); // OK. f_c(xyz_c::d);
источник
Классы перечисления («новые перечисления», «строгие перечисления») решают три проблемы с традиционными перечислениями C ++:
enums
неявно конвертируются вint
, вызывая ошибки, когда кто-то не хочет, чтобы перечисление действовало как целое число.enums
экспорт их перечислителей в окружающую область видимости, вызывая конфликты имен.enum
может быть указан, что вызывает путаницу, проблемы совместимости и делает невозможным предварительное объявление.enum class
("строгие перечисления") строго типизированы и имеют область видимости:enum Alert { green, yellow, orange, red }; // traditional enum enum class Color { red, blue }; // scoped and strongly typed enum // no export of enumerator names into enclosing scope // no implicit conversion to int enum class TrafficLight { red, yellow, green }; Alert a = 7; // error (as ever in C++) Color c = 7; // error: no int->Color conversion int a2 = red; // ok: Alert->int conversion int a3 = Alert::red; // error in C++98; ok in C++11 int a4 = blue; // error: blue not in scope int a5 = Color::blue; // error: not Color->int conversion Color a6 = Color::blue; // ok
Как показано, традиционные перечисления работают как обычно, но теперь вы можете при желании указать имя перечисления.
Новые перечисления являются «классом перечисления», потому что они сочетают в себе аспекты традиционных перечислений (имена значений) с аспектами классов (элементы с заданной областью действия и отсутствие преобразований).
Возможность указать базовый тип упрощает взаимодействие и обеспечивает гарантированные размеры перечислений:
enum class Color : char { red, blue }; // compact representation enum class TrafficLight { red, yellow, green }; // by default, the underlying type is int enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E? // (whatever the old rules say; // i.e. "implementation defined") enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // now we can be specific
Это также позволяет прямое объявление перечислений:
enum class Color_code : char; // (forward) declaration void foobar(Color_code* p); // use of forward declaration // ... enum class Color_code : char { red, yellow, green, blue }; // definition
Базовый тип должен быть одним из целочисленных типов со знаком или без знака; по умолчанию
int
.В стандартной библиотеке
enum
классы используются для:<system_error>
:enum class errc
;<memory>
:enum class pointer_safety { relaxed, preferred, strict };
<iosfwd>
:enum class io_errc { stream = 1 };
<future>
:enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
Некоторые из них имеют операторы, например
==
defined.источник
Enum Scope
Перечисления экспортируют свои перечислители в окружающую область. У этого есть два недостатка. Во-первых, это может привести к конфликту имен, если два перечислителя в разных перечислениях, объявленных в одной области, имеют одинаковое имя; во-вторых, невозможно использовать перечислитель с полным именем, включая имя перечисления.
enum ESet {a0, a, a1, b1, c3}; enum EAlpha{a, b, c} select = ESet::a; // error select = a; // is ambigious
источник