Значения enum ведут себя как глобальные переменные? - PullRequest
5 голосов
/ 24 ноября 2010

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

enum A {joe, bob, doc};
enum B {sunday, monday, doc};

Компилятор (Visual Studio) жалуется на переопределение doc, что подразумевает, что он обрабатывает его как глобальную переменную. Это так? Это не то поведение, которого я ожидал, и оно заставляет меня управлять именами всех элементов enum в моем проекте.

Любое понимание поможет.

Ответы [ 7 ]

9 голосов
/ 24 ноября 2010

Уайетт Андерсон уже предложил

namespace A
{
    enum A {joe, bob, doc};
}
namespace B
{
    enum B {sunday, monday, doc};
}

в качестве исправления для проблемы «значения перечисления находятся в той же области, что и само перечисление», что позволяет вам написать

A::doc;
B::doc;

Но это решение недоступно, когда вы хотите enum локально для класса, по крайней мере, без введения искусственного пространства имен вне класса.

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

struct A
{
    enum Enum {joe, bob, doc};
};
struct B
{
    enum Enum {sunday, monday, doc};
};

Это позволяет использовать ту же нотацию использования, что и для решения пространства имен,

A::doc;
B::doc;

, но дополнительно разрешает

  • определение внутри класса,

  • перенос имен перечисления непосредственно в класс посредством наследования и

  • локальное переименование класса в классификаторечерез typedef.

Кроме того, соглашение о присвоении имен , приведенное в качестве примера выше, позволяет

  • , на мой взгляд, немного дополнительной ясностиссылаясь на тип enum, например: A::Enum.

OK,соглашение об именах может также использоваться с решением на основе пространства имен…

Cheers & hth.,

8 голосов
/ 24 ноября 2010

Это не рассматривается как глобальная переменная . Он обрабатывается как глобальный идентификатор .

Точнее, он рассматривается как идентификатор в любом пространстве имен, в котором объявлено enum. В вашем случае это глобальное пространство имен.

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

Обычно, когда я определяю перечисления, я добавляю сокращенную версию имени идентификатора. Как это:

enum InstrumentType { itStock, itEquityOption, itFutureOption };

Это помогает избежать столкновений.

5 голосов
/ 24 ноября 2010

Перечислители в C ++ 03 имеют ту же область, что и перечисление.

enum     xxx    {    yyy,       zzz       };
          ^           ^          ^ 
    enumeration    enumerator enumerator

Это иногда удобно, иногда не совсем.

В C ++ 0x у нас будет enum class es, которые больше похожи на C # enums.А пока просто предположим (потому что это правило языка), что yyy и zzz имеют точно такую ​​же область видимости, что и xxx

4 голосов
/ 24 ноября 2010

Если вы хотите, чтобы они были глобальными, исправьте свою проблему и избегайте загрязнения пространства имен, бросая свои enum в пространство имен:

namespace A
{
    enum A {joe, bob, doc};
}
namespace B
{
    enum B {sunday, monday, doc};
}

A::doc;
B::doc;
2 голосов
/ 24 ноября 2010

Значения перечисления существуют в любой области, в которой было объявлено enum.

Следующие работы, например:

enum A {joe, bob, doc};
namespace C { enum B {sunday, monday, doc}; }

или

class A_class { enum A {joe, bob, doc}; };
class B_class { enum B {sunday, monday, doc}; };
1 голос
/ 24 ноября 2010

Значения перечисления имеют область действия самого перечисления, то есть это область объявления.Например:

enum A {value = 30};

int main()
{
   enum B {value = 32};
   int x = value;
}

x будет 32.

0 голосов
/ 28 октября 2018

Допустим, мы хотим объявить соотношение сторон для графического окна. Затем определим значения перечисления, как уже предлагалось:

struct __aspect_ratio__
{
    enum values
    {
        ASPECT_RATIO_16_9,  // HD video
        ASPECT_RATIO_16_2,  // *for testing purposes*
        ASPECT_RATIO_4_3,   // standard monitor
        ASPECT_RATIO_3_2,   // classic film
        ASPECT_RATIO_21_9,  // cinemascope
        ASPECT_RATIO_1_1    // quadratic window
    };
};

typedef __aspect_ratio__::values AspectRatio;

typedef в конце позволяет нам использовать AspectRatio::ASPECT_RATIO_16_9 как сокращение, например, подписи функций:

void SetAspectRatio(AspectRatio aspect)
{
    switch(aspect)
    {
    case AspectRatio::ASPECT_RATIO_16_9:
    // ...
    default:
            std::cerr << "Undefined aspect ratio enum value!" << std::endl;
        }
    }
}

Это работает для меня именно так, как я ожидал бы в C #.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...