Ошибка случая оператора C++ Switch

Я программирую простую текстовую RPG, используя оператор switch для игрового цикла. Программа работает нормально, пока я не попытаюсь добавить еще один оператор case, и в этот момент она выдаст мне следующие три ошибки: «перейти к метке case» (ошибка возникает в строке вновь добавленного case) и два «креста инициализации ' ClassName *objectName'" (ошибки возникают при создании новых объектов в случае 2). Я вставлю важный код, если кому-то нужно больше, дайте мне знать.

int main(void)
{
    // add weapons to array
    Weapon *weaponList[12];
    // Rusty Sword
    weaponList[0] = new Weapon(0,0,0);
    weaponList[0]->SetAll(0,2,3);
    // Bronze Sword
    weaponList[1] = new Weapon(0,0,0);
    weaponList[1]->SetAll(1,5,10);
    // Bronze Battle Axe
    weaponList[2] = new Weapon(0,0,0);
    weaponList[2]->SetAll(2,15,30);
    // Iron Sword
    weaponList[3] = new Weapon(0,0,0);
    weaponList[3]->SetAll(3,25,70);

    // add armor to array
    Armor *armorList[12];
    // Worn Platemail
    armorList[0] = new Armor(0,0,0);
    armorList[0]->SetAll(0,2,3);
    // Bronze Chainmail
    armorList[1] = new Armor(0,0,0);
    armorList[1]->SetAll(1,5,8);
    // Bronze Platemail
    armorList[2] = new Armor(0,0,0);
    armorList[2]->SetAll(2,7,20);
    // Iron Chainmail
    armorList[3] = new Armor(0,0,0);
    armorList[3]->SetAll(3,15,60);

        while(gamestate != 8)
        {
            switch(gamestate)
            {
                case 0:
                cout << " /|    Welcome!\n"
                     << " ||    \n"
                     << " ||    \n"
                     << " ||    \n"
                     << "_||_   \n"
                     << " 88    \n"
                     << " 88    Name: ";
                cin  >> heroName;
                gamestate = GAME_STATE_MENU;
                break;

            case 1:
                cout << "\n"
                     << "'/stats' will show you your stats\n"
                     << "'/shop' will let you visit the weapon shop\n"
                     << "secret commands: /setweapon #   /setarmor #   /setheroexp #\n"
                     << "\n";

                cout << "Command: ";
                cin  >> command;

                if (strcmp(command, "/stats") == 0)
                {
                    gamestate = 2;
                    break;
                }

                else if (strcmp(command, "/shop") == 0)
                {
                    gamestate = 3;
                    break;
                }

                else if (strcmp(command, "/fight") == 0)
                {
                    gamestate = 4;
                    break;
                }

                else if (strcmp(command, "/setweapon") == 0)
                {
                    cin >> testNum;
                    heroWeapon = testNum;
                    break;
                }

                else if (strcmp(command, "/setarmor") == 0)
                {
                    cin >> testNum;
                    heroArmor = testNum;
                    break;
                }

                else if (strcmp(command, "/setheroexp") == 0)
                {
                    cin >> testNum;
                    heroExp = testNum;
                    LevelUp();
                    break;
                }

                else if (strcmp(command, "/exit") == 0)
                {
                    gamestate = 8;
                    break;
                }

                else
                {
                    cout << "Please enter a valid command.\n";
                    gamestate = 2;
                    break;
                }

            case 2:
                Weapon *wCurrent = weaponList[heroWeapon];
                Armor *aCurrent = armorList[heroArmor];
                heroWeaponPower = wCurrent->GetWeaponAttack();
                heroArmorDefense = aCurrent->GetArmorDefense();
                heroPowerDefault = ((heroLevel - 1) * 10) + 10;
                heroPower = heroPowerDefault + (heroStrength * 2) + heroWeaponPower;
                heroDefenseDefault = ((heroLevel - 1) * 2) + 5;
                heroDefense = heroDefenseDefault + (heroAgility / 5) + heroArmorDefense;
                heroHealthDefault = (heroLevel * 5) + 20;
                heroHealth = heroHealthDefault + (heroStamina * 10);
                cout << "\nS T A T S\nName: " 
                     << heroName 
                     << "\nLevel: "
                     << heroLevel
                     << "\nExp: "
                     << heroExp << "/" << expForLevel[heroLevel]
                     << "\nGold: "
                     << heroGold
                     << "\nHealth: "
                     << heroHealth
                     << "\nPower: "
                     << heroPower
                     << "\nDefense: "
                     << heroDefense
                     << "\nWeapon: "
                     << weaponNameList[heroWeapon]
                     << "\nArmor: "
                     << armorNameList[heroArmor]
                     << "\n\n";
                system("PAUSE");
                gamestate = 2;
                break;

            case 3:
                break;
            }
        }

        return 0;
    }

person Community    schedule 20.03.2010    source источник
comment
Вероятно, это зависит от кода, который вы закомментировали.   -  person Brendan Long    schedule 20.03.2010
comment
Да, ваш закомментированный код, вероятно, виноват.   -  person Jaxidian    schedule 20.03.2010
comment
Зачем делать перерыв для каждой ветки if/else, когда можно сделать один перерыв для всего случая?   -  person Steve314    schedule 20.03.2010


Ответы (4)


Судя по звуку, у вас есть:

case 2:
    Type somevar = ...;
    ...
    break;

case 3:

Чтобы достичь случая 3, компилятор генерирует переход после инициализации somevar.

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

case 2:
    {
    Type somevar = ...;
    ...
    }
    break;
person Jonathan Leffler    schedule 20.03.2010

Оберните объявления в кадр стека... э-э... локальная область... :)

switch(gamestate)
{
    case 0:
    {
      Apple a;
      a.DoSomething();
    }
    break;

    case 1: /* etc. */ break;
    case 2: /* etc. */ break;
}

...или переместите их за пределы переключателя:

Apple A;
switch(gamestate)
{
     case 0: a.DoSomething(); break;
person Community    schedule 20.03.2010
comment
На самом деле это не кадр стека, а область действия блока. Хотя это правильный путь решения проблемы. - person Ben Voigt; 20.03.2010
comment
Правда, мой плохой. Однако работает аналогично с точки зрения времени жизни объекта. msdn.microsoft.com/en-us/library/ b7kfh662%28VS.80%29.aspx - person ; 20.03.2010
comment
Это была проблема! Спасибо :) - person ; 20.03.2010

Рассмотрим следующее:

switch (x)
{
    case 0:
        int i = 0;
    case 1:
        i = 5;
}

Что, если x равно 1? Затем мы пропустим инициализацию i и просто начнем его использовать. Вот что вы получаете: case 3 имеет доступ к переменным из case 2, но если вы их используете, вы начали использовать их без запуска их инициализации.

Распространенным решением является введение области видимости:

switch (x)
{
    case 0:
    {
        int i = 0;
    }
    case 1:
    {
        i = 5; // not possible, no i in this scope
    }
}
person GManNickG    schedule 20.03.2010

редактировать

Теперь, когда мы видим больше кода, проблема очевидна, это

        case 2:
            Weapon *wCurrent = weaponList[heroWeapon];
            Armor *aCurrent = armorList[heroArmor];

объявляет две переменные, поэтому вы не можете поместить после нее case, если не обернете тело case 2 в {}

оригинальный ответ ниже


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

    switch(gamestate)
    {
        case 0:
            foo a;
            break;
    }

но это позволяет случаю 1 пропустить инициализацию a, но все же ссылаться на него, поэтому он генерирует ошибку.

    switch(gamestate)
    {
        case 0:
            foo a;
            break;

        case 1:
            break;
    }

Поэтому вам нужно сделать это вместо этого, теперь область ограничена случаем 0.

    switch(gamestate)
    {
        case 0:
            {
            foo a;
            }
            break;

        case 1:
            break;
    }

Между прочим, когда вы редактировали свой код, удаляя ненужные вещи, вы также удаляли код, который вызывал проблему. ;)

person John Knoeller    schedule 20.03.2010