Использование enum внутри типов - Предупреждение компилятора C4482 C ++ - PullRequest
64 голосов
/ 05 февраля 2009

Я использую полное имя перечисления внутри метода в одном из моих классов. Но я получаю предупреждение компилятора, которое говорит "предупреждение C4482: использовано нестандартное расширение: enum 'Foo' используется в квалифицированном имени" . В C ++ нужно ли использовать перечисления без квалифицированного имени? Но ИМО, это выглядит некрасиво.

Есть мысли?

Ответы [ 8 ]

58 голосов
/ 05 февраля 2009

Да, перечисления не создают новое «пространство имен», значения в перечислении непосредственно доступны в окружающей области видимости. Итак, вы получите:

enum sample {
  SAMPLE_ONE = 1,
  SAMPLE_TWO = 2
};

int main() {
  std::cout << "one = " << SAMPLE_ONE << std::endl;
  return 0;
}
39 голосов
/ 20 августа 2011

Чтобы сделать его чистым, замените:

enum Fruit {

    ORANGE = 0,
    BANANA = 1

};

с

namespace Fruit {

    enum { //no enum name needed

        ORANGE = 0,
        BANANA = 1

    };

};

...

int f = Fruit::BANANA; //No warning
15 голосов
/ 13 апреля 2012

Хотя sth действительно отвечает на вопрос, в нем не говорится, как я всегда использовал перечисления. Несмотря на то, что они являются просто более или менее именами чисел, я всегда использовал их для определения типов, которые могут иметь только определенные значения.

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

class Apple {
  enum Variety {
    Gala,
    GoldenDelicious,
    GrannySmith,
    Fuji
  }
  ...
};

Тогда потребители смогут объявить экземпляры перечисления, передать их в качестве параметров и квалифицировать их при обращении к одному из типов.

unsigned int GetCountOfApples( Apple::Variety appleVariety );
...
fujiCnt = GetCountOfApples( Apple::Fuji );

Иногда вам нужно перечисление вне класса или два перечисления в одном классе, и вы можете сделать что-то вроде того, что было у Поя. Вы не сможете ссылаться на тип enum, поэтому просто назовите его.

namespace Color {
  enum ColorEnum {
    Blue,
    Red,
    Black
  };

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

Color::ColorEnum firstColor = Color::Blue;
Color::ColorEnum secondColor = Color::Red;

if( firstColor == secondColor )
....

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

BananaColorEnum banCol = BananaColor::Yellow;
TomatoColorEnum tomCol = TomatoColor::Yellow;
11 голосов
/ 05 февраля 2009

Да. Концептуально enum определяет тип и возможные значения этого типа. Даже если это кажется естественным, определить enum foo { bar, baz }; и затем обратиться к foo::baz - это то же самое, что указать int::1

8 голосов
/ 11 сентября 2012

namespace Company
{
    typedef int Value;
    enum
    {
        Microsoft= 0,
        APPLE = 1, 
    };
};

namespace Fruit
{
    typedef int Value;
    enum
    {
        ORANGE = 0,
        BANANA = 1,
        APPLE = 2, 
    };
};

...

Fruit::Value f = Fruit::BANANA; //No warning
Company::Value f = Company::APPLE; //is different value then Fruit::APPLE

Это работает на компиляторе GCC, MS и Mac. И преимущество в том, что вы можете использовать оператор пространства имен и передавать конфликты. Небольшой недостаток в том, что вместо Fruit вы должны написать Fruit :: Value. это более полезно в большом проекте, когда вы не знаете, что такое перечисления в другом классе.

Если вместо этого можно использовать C ++ 11, это гораздо проще, потому что тогда возможен синтаксис enum :: namespace.

7 голосов
/ 09 августа 2012

Самый простой способ сделать это - определить перечисление как таковое

namespace Samples
{
    enum Value
    {
        Sample1,
        Sample2,
        Sample3
    };
}
typedef Samples::Value Sample;

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

void Function(Sample eSample);
Sample m_eSample;

И в вашем файле .cpp вы можете использовать пространство имен для назначения переменных:

void Function(Sample eSample)
{
    m_eSample = Samples::Sample1;
    eSample = Samples::Sample2;
}
1 голос
/ 19 октября 2015

Лично я думаю, что это ошибка компилятора. Я использую C ++ много времени. К сожалению, нет примера кода в OP. Интерпретация перечисления людьми Java была на самом деле правильной iMO. Мой был таким ...

class Foo {
    enum tMyEnum { eFirstVal = 0, eSecondVal = 1};
    // ...
    tMyEnum m_myVal;
};
void Foo::MyMethod() {
    if(m_myVal == tMyEnum::eFirstVal) {
//  ...
    }
}

Я тоже пробовал, Foo :: tMyEnum :: eFirstVal. Без классификаторов все скомпилировано.

0 голосов
/ 08 марта 2018

У меня была такая же проблема, и я пока не использую C ++ 11. Я тоже предпочитаю полностью квалифицированные пространства имен.

Я отключил это конкретное предупреждение. Я уверен, что людям не понравится идея, но некоторые могут быть благодарны ..

#pragma warning( disable : 4482 )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...