использование enum говорит о недопустимом преобразовании из «int» в «type»

В моем классе я определил перечисление следующим образом:

class myClass 
{
 public:
    enum access {
      forL,
      forM,
      forA
    };
    typedef access AccessType;
    AccessType aType;
};

Позже в определен объект, подобный этому:

myClass ob;
ob->aType = 0;

Однако я получаю эту ошибку:

error: invalid conversion from 'int' to 'myClass::AccessType {aka myClass::access}' [-fpermissive]

Поля enum не сопоставляются с целыми числами?


person mahmood    schedule 02.01.2012    source источник
comment
Возможный дубликат: Приведение int к Enum в C#   -  person dani herrera    schedule 02.01.2012


Ответы (4)


Нет, они хранятся как целые числа, но это разные типы (например, вы даже можете перегрузить на основе типа перечисления). Вы должны преобразовать явно:

myClass ob;
ob->aType = (myClass::AccessType)0;

или еще лучше напишите соответствующее именованное значение перечисления:

myClass ob;
ob->aType = myClass::forL;

Или, возможно, если вы хотите использовать перечисление просто как набор целочисленных констант, измените тип поля:

class myClass 
{
 public:
    enum {
      forL,
      forM,
      forA
    };
    int aType; // just stores numbers
};

Преобразование из enum в int неявно.

person Yakov Galka    schedule 02.01.2012
comment
объект создается в другом файле. Поэтому он не распознает «forL». - person mahmood; 02.01.2012
comment
@mahmood: К сожалению, вы должны квалифицировать его с помощью myClass::. - person Yakov Galka; 02.01.2012
comment
Я написал ob->aType=myClass::access::forL;, но он говорит, что «myClass::access» не является классом или пространством имен. - person mahmood; 02.01.2012
comment
Я бы предложил правильное приведение С++ для этого: auto exampleEnum = static_cast<MyClass::AccessType>(exampleInt); - person underscore_d; 31.12.2015

Члены перечисления поддерживаются целочисленными значениями, но нет неявного преобразования из целого числа в тип перечисления. Вам нужно использовать явное приведение, если вы действительно хотите написать это так:

ob->aType = static_cast<myClass::access>(0);
person bobbymcr    schedule 02.01.2012
comment
Является ли это переносимым решением (я имею в виду предупреждения компилятора в будущем)? - person mahmood; 02.01.2012
comment
Пока указанное целое число находится в допустимом диапазоне перечисления, любой совместимый со стандартом компилятор должен разрешать это в соответствии с 7.2.10 спецификации C++: выражение арифметического или перечисляемого типа может быть явно преобразовано в перечисляемый тип. Значение не изменяется, если оно находится в диапазоне значений перечисления типа перечисления; в противном случае результирующее значение перечисления не указано. - person bobbymcr; 02.01.2012

Вы не можете выполнить неявное приведение типов из int -> enum, так как во время компиляции нет способа узнать, что приведение допустимо.

Вы можете выполнять неявные приведения по-другому, поэтому вы можете (если хотите) сделать:

int foo = forL;
person rejj    schedule 02.01.2012

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

Конструктор имеет перечисление в качестве аргумента:

enum status_t { NOT_STARTED, STARTED, DONE };
MyObject::MyObject(int id, status_t status) : m_id(id), m_status(status){}

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

MyObject::MyObject(int id, int status) : m_id(id){
    m_status = status_t(status);
}

Но нет способа быть уверенным, что значение, полученное из xml, будет в правильном диапазоне.

Вот решение, с которым я пришел:

MyObject::MyObject(int id, int status) : m_id(id){
    switch(status){
        case NOT_STARTED:
        case STARTED:
        case DONE:
            m_status=status_t(status);
            break;
        default:
            m_status=NOT_STARTED;
            break;
    }
}

Это выбор реализации, чтобы установить значение по умолчанию в случае несогласованных данных. Можно было бы предпочесть выбрасывать исключение, в моем случае так и будет.

person Pellekrino    schedule 11.07.2017