Подтвердить что ты не робот

Есть ли причина использовать перечисление для определения одной константы в коде на С++?

Типичным способом определения целочисленной константы для использования внутри функции является:

const int NumbeOfElements = 10;

то же самое для использования внутри класса:

class Class {
...
    static const int NumberOfElements = 10;
};

Затем он может использоваться как привязка массива фиксированного размера, что означает, что он известен во время компиляции.

Долгое время компиляторы не поддерживали последний синтаксис и поэтому использовали перечисления:

enum NumberOfElementsEnum { NumberOfElements = 10; }

Теперь почти каждый широко используемый компилятор, поддерживающий синтаксис in-function const int и in-class static const int, есть ли какие-либо причины для использования перечисления для этой цели?

4b9b3361

Ответ 1

Причина в основном краткость. Прежде всего, enum может быть анонимным:

 class foo {
    enum { bar = 1 };
 };

Это эффективно вводит bar как интегральную константу. Обратите внимание, что приведенное выше короче static const int.

Кроме того, никто не мог написать &bar, если он член enum. Если вы это сделаете:

 class foo {
    static const int bar = 1;
 }

а затем клиент вашего класса делает это:

 printf("%p", &foo::bar);

то он получит ошибку компоновщика-времени компоновщика, что foo::bar не определен (потому что, ну, как lvalue, это не так). На практике со стандартом, который в настоящее время стоит, где-нибудь bar используется, где интегральное постоянное выражение не требуется (т.е. Где оно просто разрешено), для него требуется определение вне класса foo::bar. такое выражение необходимо: enum инициализаторы, case метки, размер массива в типах (кроме new[]) и аргументы шаблона для интегральных типов. Таким образом, использование bar где-либо еще технически требует определения. Подробнее см. С++ Core Language Active Issue 712 - пока нет предложений.

На практике большинство компиляторов в наши дни более снисходительны к этому и позволят вам избежать большинства "здравых рассуждений" использования переменных static const int, не требуя определения. Тем не менее, угловые случаи могут отличаться, однако многие считают, что лучше использовать анонимный enum, для которого все предельно ясно, и нет никакой двусмысленности вообще.

Ответ 2

Определение статических констант непосредственно в определении класса является более поздним дополнением к С++, и многие из них по-прежнему придерживаются более старого обходного пути использования enum для этого. Там может быть даже несколько старых компиляторов, которые все еще используются, которые не поддерживают статические константы, непосредственно определенные в определениях классов.

Ответ 3

В вашем случае я бы использовал константу. Однако есть и другие случаи, когда я могу добавлять другие связанные константы. Вот так:

const int TextFile = 1; // XXX Maybe add other constants for binary files etc.?

В таких случаях я использую перечисление сразу с одним значением, например:

enum FileType {
    TextFile = 1
    // XXX Maybe add other values for binary files etc.?
}

Причина в том, что компилятор может выдавать предупреждения, когда я использую константное значение в выражениях переключателей, например:

FileType type;
// ...
switch ( type ) {
    case TextFile:
       // ...
}

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

Если бы я использовал 'int' и константы вместо этого, у компилятора не было бы возможности выдавать предупреждения.

Ответ 4

Единственная причина использования "enum hack" заключается в том, что старые компиляторы не поддерживают определения класса const, как вы говорите в своем вопросе. Итак, если вы не подозреваете, что ваш код будет перенесен на старый компилятор, вы должны использовать const, где const. Должно быть.

Ответ 5

Использование перечисления имеет одно преимущество. Тип перечисления - это тип, поэтому, если вы определяете, например:

enum EnumType { EnumValue1 = 10, EnumValue2 = 20 ... };

и у вас есть функция вроде:

void Function1(EnumType Value)

компилятор проверяет, что вы передаете элемент enum EnumType функции, поэтому только допустимые значения параметра Value будут EnumValue1 и EnumValue2. Если вы используете константы и меняете функцию на

void Function1(int Value)

компилятор проверяет, что вы передаете int (любой int, константу, переменную или литерал) в функцию.

Типы перечислений хороши для группировки связанных значений const. Только для одного значения const я не вижу никаких преимуществ.

Ответ 6

Я думаю, что нет оснований для использования перечисления и что для этой цели лучше использовать static const int, поскольку перечисление имеет свой собственный тип (даже если он неявно конвертируется в целое число).

Ответ 7

Есть разница между этими двумя. Насколько я знаю, у перечислений нет адреса. static const ints. Поэтому, если кто-то берет адрес const static int, отбрасывает const, он может изменить значение (хотя компилятор может игнорировать изменение, потому что он думает, что он const). Это, конечно, чистое зло, и вы не должны этого делать, но компилятор не может этого предотвратить. Это не может произойти с перечислениями.

И, конечно, если вам (почему-то) нужен адрес этого const, вам понадобится static const int.

Короче - enum - это rvalue, а const static int - значение l. Подробнее см. http://www.embedded.com/story/OEG20011129S0065.

Ответ 8

Ну, переносимость - хорошая причина для использования перечисления. Это здорово, потому что вам не нужно беспокоиться, поддерживает ли ваш компилятор "static const int S = 10" или нет...

Кроме того, насколько я помню, статическая переменная должна быть определена где-то, а также объявлена, и значение перечисления должно быть объявлено только.

Ответ 9

нижняя строка - используйте константу.

подробнее:

Я не эксперт на С++, но это кажется более общим вопросом дизайна.

Если это не обязательно, и вы считаете, что существует очень низкая/несуществующая вероятность того, что перечисление будет иметь более одного значения, тогда используйте регулярный const. даже если вы ошибаетесь, и в какой-то момент в будущем будет больше значений, что делает перечисление правильным выбором - простой рефакторинг, и вы меняете const на перечисление.