Переменная-член перечисления классов C++

У меня есть класс с перечисляемым типом GameStates. В (общедоступном) конструкторе я инициализирую GameStates следующим образом:

GameStates enumGameState = Ready;

Затем в общедоступном методе run() у меня есть такой переключатель:

switch(enumGameState)
        {
        case Ready:
            if (theGameEngine->KeyHit(Key_Space))
            {
                enumGameState = Firing;
                cout << "\nGame State moved to Firing";
            }   // End if
            break;
        case Firing:
            if (theGameEngine->KeyHit(Key_Space))
            {
                enumGameState = Contact;
                cout << "\nGame State moved to Contact";
            }   // End if
            break;
        case Contact:
            if (theGameEngine->KeyHit(Key_Space))
            {
                enumGameState = Over;
                cout << "\nGame State moved to Over";
            }   // End if
            break;
        case Over:
            break;
        };  // End of GameState switch

Пока код не выдает ошибки, ни одно из состояний не выполняется. Как мне получить доступ к значению enumGameState?

РЕДАКТИРОВАТЬ: весь код класса.

class Game
{
private:
    Block* arrBlocks[10][10];   
    //IMesh* objBlockMesh;
    IMesh* objGunMesh;
    IMesh* objDummyMesh;
    Gun* objGun;
    int Game::intSpeed;
    I3DEngine* theGameEngine;
    float fltSkyboxXCo;
    float fltSkyboxYCo;
    float fltSkyboxZCo;
    float fltFloorXCo;
    float fltFloorYCo;
    float fltFloorZCo;

    enum GameStates{Ready,Firing, Contact, Over};
    GameStates enumGameState;

public: 

    Game(I3DEngine* the3dengine)
    {
        Game::theGameEngine = the3dengine;
        theGameEngine->StartWindowed();

        // Add default folder for meshes and other media
        theGameEngine->AddMediaFolder( "C:\\TL-Engine\\Media\\AssigmentTwo\\Media" );

        //intSpeed = 1;

        Game::DrawBasicScene(theGameEngine);
        Game::DrawBlocks();
        Game::CreateAGun();
        Bullet::Bullet(theGameEngine);
        Game::enumGameState = Ready;
    }   // End of Constructor


private:    


    void DrawBlocks()
    {
        float fltBlockOffSet = 12.0f;
        float fltLeftMost = -54.0f;
        float fltBlockZCo = 120.0f;
        float fltBlockYCo = 5.0f;
        float fltCurrentXCo;
        float fltCurrentYCo = 5.0f;
        float fltCurrentZCo = 120.0f;
        // Stick 10 blocks in an array
        // Display them

        for(int i = 0; i < 10; i++)
        {
            if (i == 1) // Once i have created the first row all the other blocks are going to be created in a hidden state
            {
                fltCurrentYCo = -50.0f;
            }
            for(int j = 0; j < 10; j++)
            {
                fltCurrentXCo = ((float)j*fltBlockOffSet) + fltLeftMost;    // Cast j into a float explicitly so that it doesn't it implicitly
                arrBlocks[i][j] = new Block(theGameEngine, fltCurrentXCo, fltCurrentYCo, fltCurrentZCo);
                if(fltCurrentYCo < 0)
                {
                    arrBlocks[i][j]->SetBlockState(Block::Destroyed);
                }   // End if
                else
                {
                    arrBlocks[i][j]->SetBlockState(Block::New);
                }
            }   // End of inner loop

            fltCurrentZCo += fltBlockOffSet;

        }   // End of outer loop

    }

    void CreateAGun()
    {
        // Create a gun
        Gun::Gun(theGameEngine);
    }

public:
    void Game::Run()
    {
        //Start watching input in a while loop
        // The main game loop, repeat until engine is stopped
        while (theGameEngine->IsRunning())
        {
            // Draw the scene
            theGameEngine->DrawScene();
            if (theGameEngine->KeyHit(Key_Escape))
            {
                theGameEngine->Stop();
            }

            if)theGameEngine->KeyHit(Key_Space))
            {
                cout << "\n space";
            }

            GameStates currentGameState = enumGameState;
            switch(enumGameState)
            {
            case Ready:
                if (theGameEngine->KeyHit(Key_Space))
                {
                    enumGameState = Firing;
                    cout << "\nGame State moved to Firing" << endl;
                }   // End if
                break;
            case Firing:
                if (theGameEngine->KeyHit(Key_Space))
                {
                    enumGameState = Contact;
                    cout << "\nGame State moved to Contact" << endl;
                }   // End if
                break;
            case Contact:
                if (theGameEngine->KeyHit(Key_Space))
                {
                    enumGameState = Over;
                    cout << "\nGame State moved to Over" << endl;
                }   // End if
                break;
            case Over:
                break;
            };  // End of GameState switch
        }

    }
};  // End of Game Class

person Stephen Murby    schedule 05.02.2012    source источник
comment
Если вы добавите std::endl к своим отпечаткам, чтобы очистить строку, поможет ли это? std::cout << "Text" << std::endl;   -  person Martin York    schedule 05.02.2012
comment
Нет, в выводе консоли по-прежнему ничего нет. Я только что протестировал key_Space вне коммутатора, и кажется, что нажатие клавиши не читается. Что странно, так как захват клавиши escape работает нормально.   -  person Stephen Murby    schedule 05.02.2012
comment
Извините, я понимаю, что это не во фрагменте выше. Непосредственно перед переключателем у меня есть еще один theGameEngine->Key_Hit() для управляющей клавиши, которая выходит из игры. Отлично работает!   -  person Stephen Murby    schedule 05.02.2012


Ответы (4)


Если ваш конструктор имеет следующую строку кода, дословно:

GameStates enumGameState = Ready;

Затем вы только что создали local переменную enumGameState в методе конструктора и инициализировали ее. Он выходит из области видимости, как только конструктор завершает работу, и его значение теряется.

Предположительно, у вас также есть переменная member enumGameState, значение которой не инициализировано, поэтому ваш оператор switch выполняется с фиктивными значениями.

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

person Josh Kelley    schedule 05.02.2012
comment
Экземпляр GameStates определяется как enumGameState в верхней части класса, только внутри конструктора устанавливается значение Ready. - person Stephen Murby; 05.02.2012
comment
@Stephen - Тогда я не уверен, в чем проблема. Трудно сказать, не видя реального кода. - person Josh Kelley; 05.02.2012
comment
Массовый сбой, случайно добавил весь код, затем попытался удалить его, отредактировав пост, и в итоге дважды. :( Извините PS. Пожалуйста, мод может удалить лишний код? - person Stephen Murby; 05.02.2012

Вы должны определить это перечисление, чтобы использовать его:

enum GameState
{
    Ready,
    Firing,
    Contact,
    Over
};

Тогда класс Game мог бы выглядеть так:

class Game
{
public:
    Game(GameState gs = Ready) : gs(gs) { }
    void update()
    {
        switch (gs)
        {
        case Ready: cout << "Ready\n"; gs = Firing; break;
        case Firing: cout << "Firing\n"; gs = Contact; break;
        case Contact: cout << "Contact\n"; gs = Over; break;
        case Over: cout << "Over\n"; break;
        default: break;
        }
    }
private:
    GameState gs;
};

А вот и main:

int main()
{
    Game g;
    g.update();
    g.update();
    g.update();
    g.update();
    return 0;
}

выход:

Ready
Firing
Contact
Over
person LihO    schedule 05.02.2012
comment
У меня есть общедоступное перечисление GameStates и уже есть его экземпляр. который я назвал enumGameState, я присваиваю ему готовое значение в конструкторе, который также является общедоступным. Я пытаюсь использовать ту же самую переменную класса здесь, в методе. - person Stephen Murby; 05.02.2012
comment
Ну, кажется, ваша реализация была правильной. Но хорошо, что вы решили использовать enum вместо int gameState; ;) - person LihO; 06.02.2012
comment
Я думал, что делаю это правильно, но понятия не имею, почему я не получаю желаемого результата. Мне очень жаль, что я не оставил его за 24 часа до моей руки, чтобы перезапустить свое задание сейчас, хотя отладка старого была намного хуже! - person Stephen Murby; 06.02.2012
comment
Проверьте мой пример в этом ответе. Логика вашего кода остается прежней и работает нормально. - person LihO; 06.02.2012

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

Спасибо за то, что помогли мне отладить код класса Game.

person Stephen Murby    schedule 05.02.2012

Спасибо за помощь ребята. Проблема была вовсе не в классе или коде вне класса. Это была проблема с визуальной студией, к сожалению, я не уверен, что именно. Когда код был скопирован и добавлен в новый проект, он отлично скомпилировался, и все точки останова, размещенные в main, сработали.

МОРАЛЬ ИСТОРИИ: сначала попробуйте очевидное.

person Stephen Murby    schedule 07.02.2012