Последнее обновление:2026-10-12
C++ перечисления enum¶
Об авторе:¶
Личный официальный аккаунт:

Традиционное поведение¶
У перечислений есть следующие проблемы:
- Неограниченная область видимости легко приводит к конфликтам имён. Например, следующий код не компилируется:
enum Color
{
RED,
BLUE
};
enum Feeling
{
EXCITED,
BLUE
};
int main()
{
Color a = BLUE; // error
Feeling b = EXCITED;
std::cout << a << ":" << b << std::endl;
return 0;
}
Конкретная реализация: tradition_color.cpp
Классический подход¶
Простой способ решить проблему конфликтов имён, вызванную неограниченной областью видимости, — добавлять префикс к именам перечислителей: например, в примере выше заменить на COLOR_BLUE и FEELING_BLUE.
Как правило, ради единообразия добавляют префикс ко всем константам. Но код определения таких переменных перечисления выглядит громоздко. В программах на C, возможно, не обойтись без этого, однако программистам C++ такой способ вряд ли понравится. Альтернатива — пространства имён:
После этого можно определять новые переменные перечисления так: Color::Type c = Color::RED;. Если сделать using namespace Color, префикс можно вообще опустить, что упрощает код. Однако пространство имён впоследствии может пополняться новым содержимым, поэтому обеспечиваемая им закрытость области видимости невысока. В больших проектах всё же возможно, что разные люди дадут одинаковое имя разным перечислимым типам.
Более «эффективный» способ — ограничить область видимости классом или структурой; например: способ определения новых переменных такой же, как с пространством имён выше, но при этом не нужно беспокоиться, что содержимое класса изменят где-то ещё. Здесь используется структура, а не класс, потому что сами константы задуманы как общедоступные.
Конкретная реализация: classic_practice.cpp
Перечисления-классы C++11¶
Описанный выше подход решает первую проблему, но бессилен перед двумя остальными. К счастью, в стандарт C++11 были введены «перечисления-классы» (enum class), которые неплохо решают упомянутые проблемы.
- Область видимости нового enum больше не глобальная
- Не может неявно преобразовываться в другие типы
/**
* @brief C++11的枚举类
* 下面等价于enum class Color2:int
*/
enum class Color2
{
RED=2,
YELLOW,
BLUE
};
Color2 c2 = Color2::RED;
cout << static_cast<int>(c2) << endl; //必须转!
- Можно указать конкретный тип для хранения enum
enum class Color3:char; // 前向声明
// 定义
enum class Color3:char
{
RED='r',
BLUE
};
char c3 = static_cast<char>(Color3::RED);
Конкретная реализация: classic_practice.cpp
Перечислимые типы в классе¶
Иногда мы хотим, чтобы определённые константы были действительны только внутри класса. Поскольку макроконстанты, определённые через #define, глобальны и не достигают этой цели, напрашивается идея использовать члены данных, модифицированные const. Однако члены данных const действительно существуют, но их смысл не тот, которого мы ожидаем.
Член данных const константен лишь в течение времени жизни конкретного объекта, а для всего класса он изменяем, поскольку класс может создавать множество объектов, и значения члена данных const в разных объектах могут различаться.
Нельзя инициализировать член данных const в объявлении класса. Следующее применение ошибочно, поскольку до создания объекта класса компилятор не знает, чему равен SIZE. (до стандарта C++11)
Правильно делать это в списке инициализации конструктора класса:
class A
{
A(int size); // 构造函数
const int SIZE ;
};
A::A(int size) : SIZE(size) // 构造函数的定义
{
}
A a(100); // 对象 a 的 SIZE 值为 100
A b(200); // 对象 b 的 SIZE 值为 200
Как же создать константу, постоянную в рамках всего класса?
Не рассчитывайте на члены данных const — следует использовать перечислимые константы в классе. Например:
class Person{
public:
typedef enum {
BOY = 0,
GIRL
}SexType;
};
//访问的时候通过,Person::BOY或者Person::GIRL来进行访问。
Перечислимые константы не занимают памяти в объекте; они полностью вычисляются во время компиляции.
Недостаток перечислимых констант: их неявный тип данных — целочисленный, их максимальное значение ограничено, и они не могут представлять числа с плавающей точкой.
Похожие темы¶
- C++ чисто виртуальные функции и абстрактные классы | C++那些事
- C++ утверждения assert | C++那些事
- C++ битовые поля | C++那些事
- Реализация полиморфизма C++ на языке C | C++那些事
- C++ константы const и его модификация | C++那些事
- C++ всё семейство const | C++那些事
- C++ оператор разыменования * | C++那些事
- C++ инициализация и присваивание | C++那些事
- C++ возврат нескольких значений | C++那些事
- C++ ключевое слово mutable | C++那些事