Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.87/89: Рейтинг темы: голосов - 89, средняя оценка - 4.87
63 / 63 / 39
Регистрация: 18.11.2016
Сообщений: 562
1

Перечисления (enum): для чего они нужны? Как, когда и какими перечислениями уместнее пользоваться?

18.02.2017, 21:12. Показов 17381. Ответов 40

Author24 — интернет-сервис помощи студентам
Предположим есть такой код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <iomanip>
#include <Windows.h>
 
enum airplanes {SU6, SU29, SU34}; // После фигурных скобок могут идти переменные,
                                 // В книге об этом ничего не говорится, но будет интересно узнать, как ими пользваться.
    int main (){
 
        enum airpalnes how; // Как правильно использовать?
 
        int model(0);
 
        switch (model){
        case (SU6):  break;
        case (SU29): break;
        case (SU34): break;
 
        }
 
 
 
        system ("pause");
        return 0;
    }
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.02.2017, 21:12
Ответы с готовыми решениями:

Для чего нужны сужающие преобразования как они работают и на сколько они важны?
Я читаю одну книгу и застрял на одной теме &quot;Преобразования&quot;, и там есть такой вот код double х...

Что за драйвера такие, для чего они и нужны ли они вообще?
Что за драйвера такие, для чего они и нужны ли они вообще? 1 Intel SATA Preinstall driver (For...

Зачем нужны перечисления enum?
Зачем нужны перечисления enum? Почему нельзя просто использовать массив? Объясните в чем плюсы...

Struts для чего они нужны?
Привет всем! Сразу прошу не бить ногами, если кому-то вопрос показался идиотским. Но дело в том,...

40
69 / 68 / 52
Регистрация: 28.10.2015
Сообщений: 388
18.02.2017, 21:19 2
Цитата Сообщение от Photofenix Посмотреть сообщение
Для чего нужны переменные в функции перечисления?
enum нужен в тех случаях, когда нужно показать, что некая переменная должна принимать значения только из указанного списка.
0
63 / 63 / 39
Регистрация: 18.11.2016
Сообщений: 562
18.02.2017, 22:05  [ТС] 3
На примере данного кода я правильно понимаю, что переменная а относится к SU6, а переменная b относится к SU29???
C++
1
enum airplanes {SU6, SU29, SU34} a,b ;
И правильно ли я понимаю ,что enum выполняет роль списка констант?
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
18.02.2017, 22:27 4
Лучший ответ Сообщение было отмечено Photofenix как решение

Решение

Photofenix, перечисление (enum) используется, если необходимо задать несколько именованных целочисленных констант. Можно задать именованные константы так:
C++
1
2
3
const int SU6 = 0;
const int SU29 = 1;
const int SU34 = 2;
А можно воспользоваться перечислением:
C++
1
enum {SU6, SU29, SU34};
Добавлено через 19 секунд
Цитата Сообщение от Photofenix Посмотреть сообщение
правильно ли я понимаю ,что enum выполняет роль списка констант?
Да.

Добавлено через 1 минуту
Photofenix, можно задать безымянный enum:
C++
1
enum {SU6, SU29, SU34};
а можно именованный:
C++
1
enum airplanes {SU6, SU29, SU34};
Добавлено через 8 минут
Photofenix, сравните два варианта кода:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Пример #1 - с "магическими числами":
#include <iostream>
 
int main()
{
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( 0 ): // что такое ноль?
            std::cout << "This is SU-6.\n";
            break;
            
        case ( 1 ): // что означает единица?
            std::cout << "This is SU-29.\n";
            break;
            
        case ( 2 ): // что означает двойка?
            std::cout << "This is SU-34.\n";
            break;
    }
 
    return 0;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Пример #2 - с именованными константами:
#include <iostream>
 
int main()
{
    enum { SU6, SU29, SU34 };
 
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( SU6 ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( SU29 ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( SU34 ):
            std::cout << "\nThis is SU34.\n";
            break;
    }
 
    return 0;
}
Добавлено через 2 минуты
Photofenix, какой код понятнее?
2
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
18.02.2017, 23:11 5
enum зло, используйте enum class
0
56 / 56 / 31
Регистрация: 24.10.2016
Сообщений: 186
19.02.2017, 00:01 6
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
enum зло
30 лет не были злом, а тут резко с выходом c++11 они стали злом. Я с вас поражаюсь - услышали что то и повторяете, как попугаи.
Вот Страуструп по этому поводу:
• Стандартные перечисления (enums) могут неявно преобразовываться к int, что может приводить к ошибкам, если кто-то не хочет, чтобы перечисления вели себя как целые числа.
• Стандартные перечисления экспортируют свои значения в окружающую (surrounding) область видимости (scope), что приводит к коллизиям имен.
• Невозможно указать тип, лежащий в основе стандартных перечислений (underlying type), что приводит к непониманию, проблемам совместимости и делает предварительное объявление (forward declaration) невозможным.
Что здесь есть зло, которое вот прям запрещает пользоваться стандартным энумом?
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
19.02.2017, 00:24 7
OlafNestandart, вы понимаете, что enum class ввели, чтобы решать какие-то проблемы? Зачем их придумали, если enum был идеальный. И не стоит начинать дискуссию с агрессии. Объясните минусы enum хотя бы, чтобы я понял ваше мнение
0
41 / 41 / 11
Регистрация: 02.04.2016
Сообщений: 313
19.02.2017, 02:53 8
Цитата Сообщение от Photofenix Посмотреть сообщение
На примере данного кода я правильно понимаю, что переменная а относится к SU6, а переменная b относится к SU29???
Понятнее станет, когда столкнётесь с обработкой ошибок. Допустим, у приложения есть строго определённые состояния, которые изменяются функциями внутри этого приложения и почти не зависят от внешней среды - она напрямую не может изменить состояние, только через "адаптер" - функцию.

Так вот, такие состояния мне было удобно хранить с помощью переменной типа enum, в списке констант которого я указывал наименования состояний. В данном случае, значения самих констант меня не интересовали (смешно, но преподаватель по какой-то причине хотела забраковать такой подход, показав, что я ошибаюсь (типа значения этих констант всё-таки играют роль в моём коде), но, переставив несколько значений в моём списке, не добилась своего).

Удобство в следующем: при использовании switch(enum_var) компилятор контролирует количество case, которое должно быть равно количеству констант, описанных в этом enum. Это удобно в приложении на 2 тысячи строк, так как добавить тут и убрать там - очень просто, но забыть про "сям" - ещё проще. Конечно, сам я организацию кода оценивал очень плохо после последней строки кода, ибо много зависимостей.

Ну и, конечно, удобно просто называть состояния своими именами, а не 1, 2, 3.

Не по теме:

Модераторы\администраторы, почему съедаются слова в уже написанном тексте? CTRL+Z, вроде, не нажимал.



Добавлено через 2 часа 24 минуты
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
OlafNestandart, вы понимаете, что enum class ввели, чтобы решать какие-то проблемы? Зачем их придумали, если enum был идеальный. И не стоит начинать дискуссию с агрессии. Объясните минусы enum хотя бы, чтобы я понял ваше мнение
Я не OlafNestandart, но скажу, что постоянно указывать область, из которой брать переменную - немного накладно, если это единственный enum, объявленный в маленьком классе. Просто смысл уточнений области видимости всякий раз, если конфликтов в таком классе быть не может априори?

Все изменения идут на улучшение современных огромных программ. А для маленьких - смысл использовать лямбды, STD, enum class, собственные литералы, только если не в качестве самообучения? Ну, а в качестве самообучения можно и самому написать более подробные аналоги каждой конструкции из синтаксического сахара. В больших проектах использование новых возможностей само собой разумеется.

Можно ещё сказать, что Ваше поведение - это "проклятие знания", как я где-то читал. То есть, Вам уже не понять, как сложно использовать что-то более абстрактное и нацеленное на решение общих проблем, когда нужно решить частную.
1
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.02.2017, 08:36 9
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
enum зло, используйте enum class
rikimaru2013, и как переделать приведённые мной примеры с помощью enum class, если они не поддерживают неявных преобразований?

Вот такой вариант не компилируется (ни с флагом -std=c++11, ни с флагом -std=c++14):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Пример #3.
#include <iostream>
 
int main()
{
    enum class Airplane { SU6, SU29, SU34 };
 
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( Airplane::SU6 ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( Airplane::SU29 ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( Airplane::SU34 ):
            std::cout << "\nThis is SU34.\n";
            break;
 
        default:
            std::cout << "\nUnknown airplane model.\n";
    }
 
    return 0;
}
ошибки

||=== Build: Debug in C++14_MinGW_Test (compiler: GNU GCC Compiler) ===|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp||In function 'int main()':|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|13|error: could not convert 'SU6' from 'main()::Airplain' to 'int'|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|17|error: could not convert 'SU29' from 'main()::Airplain' to 'int'|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|21|error: could not convert 'SU29' from 'main()::Airplain' to 'int'|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|


Такой вариант тоже не завёлся (ни с флагом -std=c++11, ни с флагом -std=c++14):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Пример #4.
#include <iostream>
 
int main()
{
    enum class : int Airplane { SU6, SU29, SU34 };
 
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( Airplane::SU6  ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( Airplane::SU29 ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( Airplane::SU34 ):
            std::cout << "\nThis is SU34.\n";
            break;
 
        default:
            std::cout << "\nUnknown airplane model.\n";
    }
 
    return 0;
}
ошибки

||=== Build: Debug in C++14_MinGW_Test (compiler: GNU GCC Compiler) ===|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp||In function 'int main()':|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|6|error: anonymous scoped enum is not allowed|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|6|error: invalid type in declaration before '{' token|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|6|error: 'SU6' was not declared in this scope|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|6|error: 'SU29' was not declared in this scope|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|6|error: 'SU34' was not declared in this scope|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|6|error: scalar object 'Airplane' requires one element in initializer|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|14|error: 'Airplane' is not a class, namespace, or enumeration|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|18|error: 'Airplane' is not a class, namespace, or enumeration|
E:\0_0\cbProjects\C++14_MinGW_Test\main.cpp|22|error: 'Airplane' is not a class, namespace, or enumeration|
||=== Build failed: 9 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|


Получается, надо явно кастовать каждый элемент перечисления к int. У меня только так заработало:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Пример #5.
#include <iostream>
 
int main()
{
    enum class Airplane { SU6, SU29, SU34 };
 
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( static_cast<int>( Airplane::SU6 ) ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( static_cast<int>( Airplane::SU29 ) ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( static_cast<int>( Airplane::SU34 ) ):
            std::cout << "\nThis is SU34.\n";
            break;
            
        default:
            std::cout << "\nUnknown airplane model.\n";
    }
 
    return 0;
}
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.02.2017, 08:56 10
rikimaru2013, и если без явного приведения типа никак, то, как по мне, лучше уж тогда вместо enum'a использовать собственный неймспейс и несколько констант (при условии, что констант там не несколько сотен, а, скажем, три-четыре штуки):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Пример #6.
#include <iostream>
 
namespace Airplane
{
    const int SU6 = 0;
    const int SU29 = 1;
    const int SU34 = 2;
}
 
int main()
{
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( Airplane::SU6  ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( Airplane::SU29 ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( Airplane::SU34 ):
            std::cout << "\nThis is SU34.\n";
            break;
 
        default:
            std::cout << "\nUnknown airplane model.\n";
    }
 
    return 0;
}
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.02.2017, 09:06 11
А вот если использовать именованные перечисления с неограниченной областью видимости (unscoped enumeration), то есть, enum'ы старого образца, без ключевого слова class, то всё работает, как часы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Пример #7.
#include <iostream>
 
int main()
{
    enum Airplane { SU6, SU29, SU34 };
 
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( model )
    {
        case ( Airplane::SU6  ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( Airplane::SU29 ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( Airplane::SU34 ):
            std::cout << "\nThis is SU34.\n";
            break;
 
        default:
            std::cout << "\nUnknown airplane model.\n";
    }
 
    return 0;
}
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
19.02.2017, 10:37 12
Цитата Сообщение от gru74ik Посмотреть сообщение
У меня только так заработало
Во-первых, вы неправильно создаете enum class в примере #4.
Во-вторых, не то кастуете. )))
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Пример #4.
#include <iostream>
 
int main()
{
    enum class Airplane : int { SU6, SU29, SU34 };
 
    std::cout << "Enter a model of the airplane (any integer from 0 to 2): ";
    int model;
    std::cin >> model;
 
    switch ( static_cast<Airplane>(model) )
    {
        case ( Airplane::SU6  ):
            std::cout << "\nThis is SU6.\n";
            break;
 
        case ( Airplane::SU29 ):
            std::cout << "\nThis is SU29.\n";
            break;
 
        case ( Airplane::SU34 ):
            std::cout << "\nThis is SU34.\n";
            break;
 
        default:
            std::cout << "\nUnknown airplane model.\n";
    }
 
    return 0;
}
2
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.02.2017, 10:58 13
Цитата Сообщение от GbaLog- Посмотреть сообщение
Во-первых,
Благодарю.

Цитата Сообщение от GbaLog- Посмотреть сообщение
Во-вторых,
Сейчас я буду люто злоупотреблять должностными полномочиями :D
Цитата Сообщение от GbaLog- Посмотреть сообщение
вы
Ты. Обращайся ко мне на ты. Обоснование:
Цитата Сообщение от Правила форума
П. 6.6. Требования администрации форума должны выполняться немедленно и безусловно.

0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
19.02.2017, 11:06 14
Цитата Сообщение от Photofenix Посмотреть сообщение
что переменная а относится к SU6, а переменная b относится к SU29???
Нет, они оба имеют значение SU6, то есть 0, в данном случае.
Вообще, такое объявление сродни такому:
C++
1
2
3
enum airplanes {SU6, SU29, SU34};
airplanes a;
airplanes b;
А ещё енумы являются константами времени компиляции, поэтому широко используются в метарограммировании.

Добавлено через 2 минуты
Цитата Сообщение от gru74ik Посмотреть сообщение
Ты. Обращайся ко мне на ты. Обоснование:
Вообще, я забыл уже, что мы с тобой на ты, поэтому на вы обращался по привычке.
1
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.02.2017, 11:11 15
Цитата Сообщение от GbaLog- Посмотреть сообщение
А ещё енумы являются константами времени компиляции, поэтому широко используются в метарограммировании.
А вот это ценное замечание. Про это как-то никто не вспомнил.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
19.02.2017, 12:37 16
Цитата Сообщение от GbaLog- Посмотреть сообщение
C++
1
2
3
4
 int model;
 std::cin >> model;
 
switch ( static_cast<Airplane>(model) )
плохо пахнит)))
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
19.02.2017, 12:48 17
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
плохо пахнит)))
А аргументировать собираетесь? Или просто сказали, чтобы я так подумал?
0
Модератор
Эксперт CЭксперт С++
5284 / 2371 / 342
Регистрация: 20.02.2013
Сообщений: 5,770
Записей в блоге: 20
19.02.2017, 12:50 18
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
плохо пахнит)))
rikimaru2013, как сказал поэт:
Цитата Сообщение от А.С. Пушкин
Читатель ждет уж рифмы розы; На, вот возьми ее скорей!
rikimaru2013, маэстро, окажите любезность. Публика желает познать блаженство созерцания (обоняния?) хорошо пахнущего кода!
0
Croessmah
19.02.2017, 12:58
  #19

Не по теме:

Цитата Сообщение от OlafNestandart Посмотреть сообщение
30 лет не были злом
Просто замены не было.:D

0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
19.02.2017, 13:05 20
Цитата Сообщение от gru74ik Посмотреть сообщение
маэстро, окажите любезность
только ради этих фраз в воскресенье с пивом в руке, запускаю студию, чтобы выступить в виде доместоса для этого кода!
0
19.02.2017, 13:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.02.2017, 13:05
Помогаю со студенческими работами здесь

.elf и для чего они нужны
Собственно сабж Почитал Вики, как-то для новичка не очень много прояснилось И объясните еще...

.clear() и .seekg() Для чего они нужны?
Здравствуйте! Изучал код и увидел 2 интересные строки, начал гуглить, но внятного ответа не нашел,...

Allocator_traits propagate_on_container_ - для чего они нужны
В std::allocator_traits есть такие определения как propagate_on_container_copy_assignment,...

Что такое саттелиты и для чего они нужны?
Что такое саттелиты и для чего они нужны? Какую роль они играют?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru