Подтвердить что ты не робот

У двух перечислений есть некоторые общие элементы, почему это вызывает ошибку?

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

enum Month {January, February, March, April, May, June, July,
        August, September, October, November, December};
enum ShortMonth {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};

May является общим элементом обоих перечислений, поэтому компилятор говорит:

Переобучение перечислителя 'May'.

Почему он так говорит? И как я могу обойти это?

4b9b3361

Ответ 1

Имена имен перечислены в глобальной области, они должны быть уникальными. Помните, что вам не нужно квалифицировать символы перечисления с именем перечисления, вы просто:

Month xmas = December;

не

Month xmas = Month.December;  /* This is not C. */

По этой причине вы часто видите людей, которые префикс имен символов имеют имя перечисления:

enum Month { Month_January, Month_February, /* and so on */ };

Ответ 2

Я предлагаю вам объединить два:

enum Month {
  Jan, January=Jan, Feb, February=Feb, Mar, March=Mar, 
  Apr, April=Apr,   May,               Jun, June=Jun, 
  Jul, July=Jul,    Aug, August=Aug,   Sep, September=Sep, 
  Oct, October=Oct, Nov, November=Nov, Dec, December=Dec};

который будет иметь точно такой же эффект и более удобен.

Если вы хотите, чтобы в январе значение 1 вместо 0, добавьте это:

enum Month {
  Jan=1, January=Jan, Feb, February=Feb, ....

Ответ 3

В С++, чтобы избежать столкновения имен, вы могли бы перевести ваши перечисления в структуры:

struct Month { enum {January, February, March, April, May, June, July,
        August, September, October, November, December}; };
struct ShortMonth { enum {Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; };

Ответ 4

Расскажите, пожалуйста. Но я также хотел бы сказать, что ваш пример кажется довольно необычным использованием перечислений. Я не вижу значения наличия ShortMonth и LongMonth, ссылающихся на одно и то же - это имеет смысл для строк, но не для перечислений. Почему бы не просто создать один месяц для перечисления?

Ответ 5

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

enum Month {
 January, Jan = January,
 February, Feb = February,
 March, Mar = March,
 April, Apr = April
 May,
 June, Jun = June,
 July, Jul = July,
 ...};

И чтобы иметь разные имена представлений (короткие и длинные), у вас должно быть два различных строковых массива, индексированных перечислением.

char[MAX_MONTH_NAME_LENGTH][12] month_long_names = {
  "January", "February", ...
}

char[3][12] short_long_names = {
  "Jan", "Feb", ...
}

printf("month %d long name is %s, and short name is %s\n", May, long_month_names[May], short_month_names[May]);

Ответ 6

В C перечислениях используются без префикса любого типа, поэтому вы пишете:

month[0] = January;  
month[4] = May;

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

Ответ 7

В С++ 11 вы можете использовать scoped перечисления, чтобы исправить это. Это позволит удалить имена из глобальной области и объединить их в имя перечисления.

enum class Identity
{
       UNKNOWN = 1,
       CHECKED = 2,
       UNCHECKED =3
};

enum class Status
{
       UNKNOWN = 0,
       PENDING = 1,
       APPROVED = 2,
       UNAPPROVED =3
};

int main ()
{
    Identity::UNKNOWN;
    Status::UNKNOW;
}

Живой пример

Ответ 8

typedef enum {Jan, January, Feb, February, Mar, March, Apr, April, May, Jun, June, Jul, July,
    Aug, August, Sep, September, Oct, October, Nov, November, Dec, December} Month,ShortMonth;

Объединить их в один