problem with abstract classes???

I'm trying to learn SDL from a book (pakit - sdl game development) and was at the bit with gamestates.

then i try to compile the program and i get these mesages in my build log:-


C:\Users\Home\Code\SDL_GameDev\Game.cpp:51:42: error: expected type-specifier before 'MenuState'
C:\Users\Home\Code\SDL_GameDev\Game.cpp:51:42: error: expected ')' before 'MenuState'
C:\Users\Home\Code\SDL_GameDev\Game.cpp:51:53: error: no matching function for call to 'GameStateMachine::changeState(int*)'
C:\Users\Home\Code\SDL_GameDev\Game.cpp:51:53: note: candidate is:
In file included from C:\Users\Home\Code\SDL_GameDev\Game.h:13:0,
from C:\Users\Home\Code\SDL_GameDev\Game.cpp:1:
C:\Users\Home\Code\SDL_GameDev\GameStateMachine.h:11:14: note: void GameStateMachine::changeState(GameState*)
C:\Users\Home\Code\SDL_GameDev\GameStateMachine.h:11:14: note: no known conversion for argument 1 from 'int*' to 'GameState*'

((I deleted similar stuff as above but for 'GameState' to make the post fit ))
6 errors, 0 warnings (0 minutes, 0 seconds)


I've been at this for hours now and its doing my nut in, please could someone help. I've tried toying about with the moving the #includes around but I end up getting other errors.

I'll try past the relevant code

Game.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <SDL_image.h>
#include <iostream>
#include <vector>
#include "TextureManager.h"
#include "GameObject.h"
#include "SDLGameObject.h"
#include "Player.h"
#include "Enemy.h"
#include "InputHandler.h"
#include "GameStateMachine.h"
//#include "GameState.h"
//#include "MenuState.h"
//#include "PlayState.h"

class Game
{
    public:
        static Game * Instance()
        {
            if(s_pInstance == 0)
            {
                s_pInstance = new Game();
                return s_pInstance;
            }
            return s_pInstance;
        }

        SDL_Renderer * getRenderer() const { return m_pRenderer; }

        bool init(const char * title, int xpos, int ypos, int width, int height, bool fullscreen);
        void render();
        void update();
        void handleEvents();
        void clean();

        bool running(){return m_bRunning;}

    protected:
    private:
        Game(){}
        virtual ~Game(){}
        static Game * s_pInstance;

        SDL_Window * m_pWindow;
        SDL_Renderer * m_pRenderer;

        std::vector<GameObject*> m_gameObjects;

        int m_currentFrame;

        bool m_bRunning;

        GameStateMachine* m_pGameStateMachine;
};

typedef Game theGame;


#endif // GAME_H 


Game.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "Game.h"

Game * Game::s_pInstance = 0;

// SDL Initialize *************************************************************
bool Game::init(const char * title, int xpos, int ypos, int width,
                int height, bool fullscreen)
{
    // attepmt to initialize sdl
    if(SDL_Init(SDL_INIT_EVERYTHING) == 0)
    {
        std::cout << "SDL Init success.\n";
        // Init the window
        m_pWindow = SDL_CreateWindow(title,  xpos, ypos, width, height, fullscreen);
        if(m_pWindow != 0)
        {
            std::cout << "SDL Window success.\n";
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, 0);

            if(m_pRenderer != 0)
            {
                std::cout << "SDL Renderer success.\n";
                SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);
            }else
            {
                std::cout << "SDL Renderer fail.\n";
                return false;
            }
        }else
        {
                std::cout << "SDL Window fail.\n";
                return false;
        }
    }else
    {
        std::cout << "SDL Init fail.\n";
        return false;
    }

    std::cout << "SDL Success.\n";
    m_bRunning = true;

    if(!theTextureManager::Instance()->load("images/animate.bmp", "animate", m_pRenderer))
    {
        return false;
    }

    TheInputHandler::Instance()->initializeJoysticks();

    m_pGameStateMachine = new GameStateMachine();
    m_pGameStateMachine->changeState(new MenuState());

   // m_gameObjects.push_back(new Player(new LoaderParams(100, 100, 128, 82, "animate")));
   // m_gameObjects.push_back(new Enemy(new LoaderParams(300, 300, 128, 82, "animate")));

    return true;
}



// Renderer Function **********************************************************
void Game::render()
{
    SDL_RenderClear(m_pRenderer);

    m_pGameStateMachine->render();

    SDL_RenderPresent(m_pRenderer);
}

void Game::update()
{
    m_pGameStateMachine->update();
}

// Cleanup Function ***********************************************************
void Game::clean()
{
    std::cout << "SDL Cleanup complete.\n";
    SDL_DestroyWindow(m_pWindow);
    SDL_DestroyRenderer(m_pRenderer);
    TheInputHandler::Instance()->clean();
    SDL_Quit();
}

// Handle Events function *****************************************************
void Game::handleEvents()
{
   TheInputHandler::Instance()->update();

   if(TheInputHandler::Instance()->isKeyDown(SDL_SCANCODE_RETURN))
   {
       m_pGameStateMachine->changeState(new PlayState());
   }
}


GameState.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef GAMESTATE_H
#define GAMESTATE_H
#include <string>

class GameState
{
    public:
        GameState(){}
        virtual ~GameState(){}
        virtual void update() =0;
        virtual void render() =0;
        virtual bool onEnter() =0;
        virtual bool onExit() =0;

        virtual std::string getStateID() =0;
        //virtual ~GameState();
    protected:
    private:
};

#endif // GAMESTATE_H 


MenuState.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef MENUSTATE_H
#define MENUSTATE_H
#include "GameState.h"
#include <string>

class MenuState : public GameState
{
    public:
        MenuState(){}
        virtual ~MenuState(){}
        virtual void update();
        virtual void render();
        virtual bool onEnter();
        virtual bool onExit();

        virtual std::string getStateID() const {return s_menuID;}
     //   virtual ~MenuState();

    protected:
    private:
        static const std::string s_menuID;
};

#endif // MENUSTATE_H 


MenuState.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "MenuState.h"

const std::string MenuState::s_menuID = "MENU";

void MenuState::update()
{
    //
}

void MenuState::render()
{
    //
}

bool MenuState::onEnter()
{
    std::cout << "entering MenuState.\n";
    return true;
}

bool MenuState::onExit()
{
    std::cout << "exiting MenuState.\n";
    return true;
}


GameStateMachine.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "GameState.h"
#include <vector>
class GameStateMachine
{
    public:

        GameStateMachine(){}
        void pushState(GameState* pState);
        void changeState(GameState* pState);
        void popState();

        void update();
        void render();

        virtual ~GameStateMachine(){}
    protected:
    private:

        std::vector<GameState*> m_gameStates;
};

#endif // GAMESTATEMACHINE_H 


GameStateMachine.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include "GameStateMachine.h"

void GameStateMachine::pushState(GameState* pState)
{
    m_gameStates.push_back(pState);
    m_gameStates.back()->onEnter();
}

void GameStateMachine::popState()
{
    if(!m_gameStates.empty())
    {
        if(m_gameStates.back()->onExit())
        {
            delete m_gameStates.back();
            m_gameStates.pop_back();
        }
    }
}

void GameStateMachine::changeState(GameState* pState)
{
    if(!m_gameStates.empty())
    {
        if(m_gameStates.back()->getStateID() == pState->getStateID())
        {
            return; // do nothing
        }

        if(m_gameStates.back()->onExit())
        {
            delete m_gameStates.back();
            m_gameStates.pop_back();
        }
    }
    // push back new state
    m_gameStates.push_back(pState);

    // initialize it
    m_gameStates.back()->onEnter();
}

void GameStateMachine::update()
{
    if(!m_gameStates.empty())
    {
        m_gameStates.back()->update();
    }
}

void GameStateMachine::render()
{
    if(!m_gameStates.empty())
    {
        m_gameStates.back()->render();
    }
}


I hope that's all it, I didn't paste the GameState.h and .cpp because its basically a copy of MenuState.h .cpp
Your Game.cpp does not include MenuState.h and therefore its line 51 has no idea what the identifier "MenuState" means.
When I include them I i then get these messages


-------------- Build: Debug in SDL_GameDev (compiler: GNU GCC Compiler)---------------

mingw32-g++.exe -Wall -g -std=c++11 -IC:\SDL2-devel-2.0.3-mingw\SDL2-2.0.3\include -c C:\Users\Home\Code\SDL_GameDev\Game.cpp -o obj\Debug\Game.o
C:\Users\Home\Code\SDL_GameDev\Game.cpp: In member function 'bool Game::init(const char*, int, int, int, int, bool)':
C:\Users\Home\Code\SDL_GameDev\Game.cpp:51:52: error: cannot allocate an object of abstract type 'MenuState'
In file included from C:\Users\Home\Code\SDL_GameDev\Game.h:15:0,
from C:\Users\Home\Code\SDL_GameDev\Game.cpp:1:
C:\Users\Home\Code\SDL_GameDev\MenuState.h:6:7: note: because the following virtual functions are pure within 'MenuState':
In file included from C:\Users\Home\Code\SDL_GameDev\GameStateMachine.h:3:0,
from C:\Users\Home\Code\SDL_GameDev\Game.h:13,
from C:\Users\Home\Code\SDL_GameDev\Game.cpp:1:
C:\Users\Home\Code\SDL_GameDev\GameState.h:15:29: note: virtual std::string GameState::getStateID()
C:\Users\Home\Code\SDL_GameDev\Game.cpp: In member function 'void Game::handleEvents()':
C:\Users\Home\Code\SDL_GameDev\Game.cpp:93:55: error: cannot allocate an object of abstract type 'PlayState'
In file included from C:\Users\Home\Code\SDL_GameDev\Game.h:16:0,
from C:\Users\Home\Code\SDL_GameDev\Game.cpp:1:
C:\Users\Home\Code\SDL_GameDev\PlayState.h:6:7: note: because the following virtual functions are pure within 'PlayState':
In file included from C:\Users\Home\Code\SDL_GameDev\GameStateMachine.h:3:0,
from C:\Users\Home\Code\SDL_GameDev\Game.h:13,
from C:\Users\Home\Code\SDL_GameDev\Game.cpp:1:
C:\Users\Home\Code\SDL_GameDev\GameState.h:15:29: note: virtual std::string GameState::getStateID()
Process terminated with status 1 (0 minutes, 0 seconds)
2 errors, 0 warnings (0 minutes, 0 seconds)

This is confusing me as well since I have basically copied the code from a book... I must read up on virtual functions more I guess..
Your code has:
1
2
virtual std::string GameState::getStateID()
virtual std::string MenuState::getStateID() const

Do you now see why MenuState does not provide implementation for all pure virtual methods of GameState?
Ahh yeah the const, I didn't even notice. Thanks it compiled now.



Topic archived. No new replies allowed.