Почему я не могу назначить неправильный элемент перечисления, но могу сравнить с неправильным элементом перечисления? - PullRequest
7 голосов
/ 06 июля 2011

Со следующими определениями C ++:

enum EnumA {
    EA_Element = 1
};

enum EnumB {
    EB_Element = 10
};

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

EnumA variable;
variable = EB_Element; // won't compile

но следующий код компилируется:

EnumA variable = EA_Element;
if( variable == EB_Element ) { //will compile
}

хотя это не имеет никакого смысла - сравниваются разные перечисления, и такой код, вероятно, ошибочен.

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

Ответы [ 4 ]

6 голосов
/ 06 июля 2011

Компилируется, потому что «по умолчанию перечисления преобразуются в целые числа для арифметических операций». (В кн .: Язык программирования C ++)

4 голосов
/ 06 июля 2011

Этот аргумент верен, поскольку я видел, что любой тип enum можно сравнить с любым типом enum. Это потому, что для сравнения enum переменные и значения должны быть преобразованы в целочисленный тип (например, int). Определенный компилятор выдает предупреждение .

Такой аргумент может иметь значение true для сравнения между unsigned int, int, size_t и т. Д., Но, возможно, все они ограничены предупреждением компилятора по той же причине.

Однако эта проблема решена в C ++ 0x с помощью enum class (они не изменили существующее поведение enum для поддержания совместимости).

2 голосов
/ 06 июля 2011

Это не так, что это невозможно, просто ваш компилятор считает их двумя разными типами данных, когда они оба являются целыми числами. Таким образом, простой тип-тип решит проблему.

EnumA variable;
variable = (EnumA)EB_Element;
1 голос
/ 06 июля 2011

Добро пожаловать в C ++!

для чего-то еще более забавного попробуйте это:

#include <string>

int main(int argc, const char *argv[])
{
    std::string s;
    s = 3.141592654;
    return 0;
}

почему он компилируется?Причина в том, что языковые правила так говорят.

В этом странном случае «официальное» объяснение того, почему этот пример компилируется, состоит в том, что казалось правильным разрешить std::string::operator+=(char) (IMO нормально и логично с прагматической точки зренияview) и "следовательно" также присваивание от char (IMO нелогично не sequitur).Но символы - это целые числа (нелогично, но наследие Си), а двойники могут быть неявно преобразованы в целые числа (нелогично, но наследие Си).Поэтому в C ++ нелогично (но законно) присваивать строковое значение double.

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

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

Если вы чувствуете себя некомфортно из-за очевидного отсутствия логики, пожалуйста, помните, что C ++ в основном является результатом долгой истории и даже комитета (!), Поэтому логика недействительно много общего с этим.Это также подразумевает, что нельзя использовать логику, чтобы избежать изучения C ++: независимо от того, насколько вы умны, вы не сможете угадать исторические происшествия и политические решения комитета.

Высокая сложность C ++, это отсутствие логики во многихместа и наличие undefined behavior daemons вместо runtime error angels - это также то, что IMO в основном исключает изучение C ++ экспериментальным путем.

Выберите хорошую книгу (или несколько) и прочитайте ее (их) от корки до корки... к сожалению, нет другого пути.Мои предложения: «Язык программирования C ++» (Stroustrup), «Эффективный C ++» и «Более эффективный C ++» (Meyers), «Часто задаваемые вопросы по C ++» (Cline / Lomow / Girou).

C ++ довольно симпатичныймощное и приятное оружие для владения, но подходите к нему не с той стороны, и это может стать худшим из ваших кошмаров.Предполагать, что вы можете понять это, просто используя логику, является неправильным подходом (и не потому, что ваша логика слаба, а потому, что C ++ - это не просто логика).

...