Почему люди используют перечисления в C++ как константы, в то время как они могут использовать константу?

Удостоверьтесь, что thisMonth является по крайней мере плавающей или двойной, а не целым числом:

String quarter = thisMonth/3 <= 1 ? "Q1" : thisMonth/3 <= 2 ? "Q2" : thisMonth/3 <= 3 ? "Q3" : "Q4";

С уважением, MS

33
задан Trott 17 September 2011 в 22:52
поделиться

12 ответов

Перечисление подразумевает набор связанных констант, поэтому добавленная информация об отношении должна быть полезна в их модели рассматриваемой проблемы.

23
ответ дан 27 November 2019 в 17:22
поделиться

Брюс Экель объясняет причину в Thinking in C ++ :

В более старых версиях C ++ static const не поддерживалось внутри классов. Это означало, что const бесполезно для константных выражений внутри классов. Тем не менее, люди по-прежнему хотели это сделать, поэтому типичным решением (обычно называемым «enum hack») было использование нетегированного enum без экземпляров. Все значения перечисления должны быть установлены во время компиляции, они локальны для класса и их значения доступны для константных выражений. Таким образом, вы обычно увидите:

 #include 
используя пространство имен std;

class Bunch {
 перечисление {размер = 1000};
 int я [размер];
};

int main () {
 cout << "sizeof (связка) =" << sizeof (связка) 
 << ", sizeof (i [1000]) =" 
 << sizeof (int [1000]) << endl;
}
 

[Edit]

Я думаю, что было бы более справедливо указать ссылку на сайт Брюса Эккеля: http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html .

45
ответ дан 27 November 2019 в 17:22
поделиться

Имеется также историческая причина, когда дело касается метапрограммирования шаблонов. Некоторые компиляторы могут использовать значения из перечисления, но не статическую const int для создания экземпляра класса.

template <int N>
struct foo
{
    enum { Value = foo<N-1>::Value + N };
};

template <>
struct foo<0>
{
    enum { Value = 0; }
};

Теперь вы можете сделать это более разумным способом:

template <int N>
struct foo
{
    static const int Value = foo<N-1>::Value + N;
};

template <>
struct foo<0>
{
    static const int Value = 0;
};

Другая возможная причина в том, что статическая const int может иметь зарезервированную память для него во время выполнения, тогда как у перечисления никогда не будет фактического места в памяти, зарезервированного для него, и он будет обработан во время компиляции. См. этот связанный вопрос.

20
ответ дан 27 November 2019 в 17:22
поделиться

Перечисления - это разные типы, поэтому вы можете выполнять с ними ориентированные на типы вещи, например перегрузку:

enum Color { Red,Green,Blue };
enum Size { Big,Little };

void f( Color c ) {
}

void f( Size s ) {
}

int main() {
    f( Red );
    f( Big );
}
36
ответ дан 27 November 2019 в 17:22
поделиться

При использовании перечисления более информативны. Рассмотрим:

int f(int fg, int bg)

по сравнению с

 int f(COLOR fg, COLOR bg)

Кроме того, перечисления обеспечивают немного большую безопасность типов, потому что

  • целые числа не могут быть неявно преобразованы в перечисляемые типы
  • перечисление одного типа не может быть неявно преобразовано в перечисление другого типа
10
ответ дан 27 November 2019 в 17:22
поделиться

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

enum {NONE, START, HEY, HO, LAST};

Тогда легко выполнить цикл до ПОСЛЕДНЕГО, и когда будет добавлено новое состояние (или что-то другое) , логика адаптируется.

for (int i = NONE; i < LAST; i++)
{
    // Do stuff...
}

Добавьте что-нибудь ...

enum {NONE, START, HEY, WEE, HO, LAST};

Цикл адаптируется ...

10
ответ дан 27 November 2019 в 17:22
поделиться

До того, как поставщики компиляторов внедрили стандарт ISO / IEC 14882: 1998 C ++, этот код определение константы в области класса привело к ошибке компиляции:

class Foo {
    static const int MAX_LEN = 80;
    ...
};

Если константа является целочисленным типом, непростая работа заключается в определении ее в перечислении внутри класса:

class Foo {
    enum {
        MAX_LEN = 80
    };
    ...
};
5
ответ дан 27 November 2019 в 17:22
поделиться

перечисления также могут использоваться как имя типа. Таким образом, вы можете определить функцию, которая принимает перечисление в качестве параметра, что делает более ясным, какие типы значений следует передавать в качестве аргументов функции, по сравнению со значениями, определенными как константные переменные, и функцией, принимающей только "int" в качестве аргумента.

Рассмотрим:

enum my_new_fangled_type {
  baz = 0,
  meh = 1
};

void foo (my_new_fangled_type bar) // bar can be a value listed in the enum
{
   ...
}

против:

int const baz = 0;
int const meh = 1;

void foo (int bar) // what are valid values for bar?
{
   ...
}
4
ответ дан 27 November 2019 в 17:22
поделиться

попробуйте EMS Advanced Data Export VCL

http://sqlmanager.net/en/products/tools/advancedexport

  • Экспорт данных (наборов данных) в 17 самых популярных форматов: MS Access , MS Excel, MS Word, формат Open XML, формат открытого документа (ODF), RTF, HTML, XML, PDF, TXT, DBF, CSV, SYLK, DIF, LaTeX, SQL и буфер обмена Windows
  • Borland Delphi 5-7 , 2005, 2006, CodeGear Delphi 2007, 2009 и Borland C ++ Builder 5-6, CodeGear C ++ Builder 2007, 2009 поддерживают
  • Экспорт данных Unicode. Ручная настройка кодировки текста для экспортируемых данных (UTF-8, UTF-16 / UCS-2, UTF-32 / UCS-4, Latin1, Latin2, Latin5, Latin7 и др.)
  • Сохранение данных для будущего просмотра, изменения,
0
ответ дан 27 November 2019 в 17:22
поделиться

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

enum { Val1, Val2, Val3 };

... вместо ...

const int Val1=0, Val2=1, Val3=2;
-1
ответ дан 27 November 2019 в 17:22
поделиться

Это отчасти потому, что старые компиляторы не поддерживали объявление истинной константы класса

class C
{
  const int ARealConstant = 10;
};

, поэтому пришлось сделать это

class C
{
  enum { ARealConstant = 10 };
};

По этой причине многие переносимые библиотеки продолжают использовать эту форму.

Другая причина заключается в том, что перечисления могут использоваться в качестве удобного синтаксического устройства для организации констант классов на те, которые связаны, и те, которые не являются

class DirectorySearcher
{
  enum options
  {
    showFiles = 0x01,
    showDirectories = 0x02,
    showLinks = 0x04,
  };
};

vs

class Integer
{
   enum { treatAsNumeric = true };
   enum { treatAsIntegral = true };
   enum { treatAsString = false };
};
2
ответ дан 27 November 2019 в 17:22
поделиться

Некоторые отладчики будут отображать имя перечисления вместо его значения при отладке. Это может быть очень полезно. Я знаю, что предпочитаю day_of_week = MONDAY , чем day_of_week = 1 .

2
ответ дан 27 November 2019 в 17:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: