Здесь документация относительно приоритета оператора
in binds tighter than not
Настолько делающий, так будет служить цели
>>> (not True) in [False, True]
True
Причина в основном в краткости. Прежде всего, перечисление
может быть анонимным:
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 это не так). На практике, со стандартом в его нынешнем виде, везде используется полоса
, где выражение интегральной константы не требуется (т. Е. Где это просто разрешено), требуется исключение из -класс определения foo :: bar.
Места, где требуется такое выражение: enum
инициализаторы, case
метки, размер массива в типах (кроме new []
) и шаблон аргументы целочисленных типов. Таким образом, использование бара
где-либо еще технически требует определения. См. C ++ Core Language Active Issue 712 для получения дополнительной информации - на данный момент нет предлагаемых решений.
На практике большинство компиляторов в наши дни более снисходительно относятся к этому и позволят вам уйти от большинства «здравый смысл» использует переменные static const int
, не требуя определения. Однако угловые случаи могут различаться, поэтому многие считают, что лучше просто использовать анонимное enum
, для которого все кристально ясно и нет никакой двусмысленности.
Определение статических констант непосредственно в определении класса является более поздним дополнением к C ++, и многие по-прежнему придерживаются более старого обходного пути использования для этого перечисления
. Возможно, до сих пор используются несколько старых компиляторов, которые не поддерживают статические константы, прямо определенные в определениях классов.
Единственная причина для использования "enum hack" состоит в том, что старые компиляторы не поддерживают определения констант внутри класса, как вы говорите в своем вопросе. Итак, если вы не подозреваете, что ваш код будет перенесен на старый компилятор, вам следует использовать const там, где требуется const.
В вашем случае я бы тоже использовал константу. Однако есть и другие случаи, когда я мог бы добавлять другие связанные константы. Примерно так:
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.?
}
Причина в том, что компилятор может затем выдавать предупреждения, когда я использую постоянное значение в выражениях переключателя, как in:
FileType type;
// ...
switch ( type ) {
case TextFile:
// ...
}
В случае, если я решу добавить другое постоянное значение, которое связано с существующим значением (в данном примере это другой тип файла), практически все компиляторы выдадут предупреждение, так как новое значение не обрабатывается в переключателе оператор.
Если бы я использовал вместо этого int и константы, у компилятора не было бы возможности выдавать предупреждения.
Использование перечисления имеет одно преимущество. Тип перечисления - это тип, поэтому, если вы определяете, например:
enum EnumType { EnumValue1 = 10, EnumValue2 = 20 ... };
, и у вас есть такая функция, как:
void Function1(EnumType Value)
, компилятор проверяет, что вы передаете член перечисления EnumType функции, поэтому только допустимые значения для Значение параметра будет EnumValue1 и EnumValue2. Если вы используете константы и изменяете функцию на
void Function1(int Value)
, компилятор проверяет, что вы передаете в функцию int (любой int, константу, переменную или литерал).
Перечислимые типы хороши для группировки связанных константных значений. Только для одного значения const я не вижу никаких преимуществ.
Я думаю, что нет причин использовать перечисление, и что на самом деле лучше использовать для этой цели static const int
, поскольку перечисление имеет свой собственный тип ( даже если неявно конвертируется в целое число).
Между этими двумя есть разница. Насколько я знаю, у перечислений нет адреса. статические константы, хотя Поэтому, если кто-то берет адрес const static int, отбрасывает const, он может изменить значение (хотя компилятор может игнорировать изменение, потому что он думает, что это const). Это, конечно, чистое зло, и вы не должны этого делать, но компилятор не может этого предотвратить. Этого не может произойти с перечислениями.
И, конечно же - если вам (по какой-то причине) нужен адрес этой const, вам понадобится static const int.
Короче говоря, enum - это rvalue, а const static int это lvalue. См. http://www.embedded.com/story/OEG20011129S0065 для получения дополнительной информации.
Ну, переносимость является хорошей причиной для использования enum. Это здорово, потому что вам не нужно беспокоиться о том, поддерживает ли ваш компилятор "static const int S = 10" или нет ...
Кроме того, насколько я помню, статическая переменная должна быть где-то определена, как и объявлено, и должно быть объявлено только значение перечисления.
нижняя строка - используйте const.
подробнее:
Я не эксперт по C ++, но это кажется более общим вопросом дизайна.
Если это не обязательно, и вы считаете, что вероятность того, что перечисление вырастет до более чем одного значения, очень мала / отсутствует, тогда используйте обычную константу. даже если вы ошибаетесь и в какой-то момент в будущем будет больше значений, что делает enum правильным выбором - простой рефакторинг, и вы меняете const на enum.