Есть ли причина использовать перечисление для определения одной константы в коде на С++?
Типичным способом определения целочисленной константы для использования внутри функции является:
const int NumbeOfElements = 10;
то же самое для использования внутри класса:
class Class {
...
static const int NumberOfElements = 10;
};
Затем он может использоваться как привязка массива фиксированного размера, что означает, что он известен во время компиляции.
Долгое время компиляторы не поддерживали последний синтаксис и поэтому использовали перечисления:
enum NumberOfElementsEnum { NumberOfElements = 10; }
Теперь почти каждый широко используемый компилятор, поддерживающий синтаксис in-function const int
и in-class static const int
, есть ли какие-либо причины для использования перечисления для этой цели?
Ответы
Ответ 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 на перечисление.