Andria
Andria

Reputation: 5075

C++ error expected class-name before '{' token

I know many, many others have posted about this but I am so lost, due to so many people saying forward declaration and other massively confusing things that I can't seem to find a way to use without bringing up new errors in my compiler so if anyone could help me that would be much appreciated.

I am using Code::Blocks on Ubuntu 15.04

The Error is OptimizedSurface.h|11|error: expected class-name before ‘{’ token

In the OptimizedSurface Header file I decided to do class OptimizedSurface : Game{ because before this error I was getting

include/Game.h|18|error: invalid use of member ‘Game::windowSurface’ in static member function the line was optimized_surface = SDL_ConvertSurface(surface, Game::windowSurface->format, 0);

And now the the code is the below files.

main.cpp -

#include "Game.h"
#include <stdio.h>


int main(int argc, char* args[]){
    printf("Initializing Game class\n");
    Game game = Game();
    return 0;
}

Game.h -

#ifndef GAME_H
#define GAME_H

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include <stdio.h>
#include <chrono>
#include <thread>
#include <iostream>
#include "MenuState.h"

class MenuState;

class Game{
    public:
        Game();
        virtual ~Game();
        SDL_Surface *windowSurface = nullptr;

    protected:

    private:
        void tick();
        void update_time();
        std::chrono::system_clock::time_point now, last_frame;
        int delta = 0;
        void event_handler();
        void render();

        // Screen Dimensions
        const int SCREEN_WIDTH = 640;
        const int SCREEN_HEIGHT = 480;

        //Main Window
        SDL_Window *window = nullptr;

        // Surfaces
        SDL_Surface *currentImage = nullptr;

        // Main Menu Screen
        MenuState *menu;

        bool isRunning = true;

        // Main Menu = 1; Game = 2; Paused = 3;
        int currentState = 1;

        // Events
        SDL_Event ev;
};

#endif // GAME_H

Game.cpp -

#include "Game.h"


Game::Game(){
    // Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );

    else{
        this->menu = new MenuState;
        // Create Window
        this->window = SDL_CreateWindow( "Tetris", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );

        if( this->window == NULL ){
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
        }

        else{
            // Get window surface
            this->windowSurface = SDL_GetWindowSurface( this->window );

            // Fill the surface white
            SDL_FillRect( this->windowSurface, NULL, SDL_MapRGB( this->windowSurface->format, 0xFF, 0xFF, 0xFF ) );

            // Update the Surface
            SDL_UpdateWindowSurface( this->window );

            //Set current image to display as main menu
            this->currentImage = this->menu->MenuSurface[ 0 ];
            this->tick();
        }
    }
}

void Game::tick(){
    while( this->isRunning ){
        if( !( this->delta >= 33 ) )
            this->update_time();
        else{
            this->last_frame = std::chrono::system_clock::now();
            this->event_handler();
            this->render();
        }
    }
}

void Game::update_time(){
    this->now = std::chrono::system_clock::now();
    this->delta = std::chrono::duration_cast<std::chrono::milliseconds>(this->now - this->last_frame).count();
}

void Game::event_handler(){
    while( SDL_PollEvent( &this->ev ) != 0 && this->currentState == 1){
        switch( this->ev.type ){
            case SDL_MOUSEBUTTONDOWN:
                if( this->ev.button.button  == SDL_BUTTON_LEFT )
                    if( this->menu->checkPos( this->ev.button.x, this->ev.button.y ) )
                        this->currentImage = this->menu->MenuSurface[ 2 ];
                    break;

            case SDL_MOUSEBUTTONUP:
                if( this->ev.button.button == SDL_BUTTON_LEFT )
                    if( this->menu->checkPos( this->ev.button.x, this->ev.button.y ) )
                        currentState = 2;
                        // Start the Game
            default:
                if( this->menu->checkPos( this->ev.button.x, this->ev.button.y ) )
                    this->currentImage = this->menu->MenuSurface[ 1 ];
                else
                    this->currentImage = this->menu->MenuSurface[ 0 ];
                break;
        }
    }
    if( this->ev.type == SDL_QUIT )
        this->isRunning = false;
}

void Game::render(){
    SDL_BlitSurface( this->currentImage, NULL, windowSurface, NULL );
    SDL_UpdateWindowSurface( window );
}

Game::~Game(){
    // Destroy Everything
    this->currentImage = nullptr;

    SDL_DestroyWindow( this->window );
    this->window = nullptr;

    delete menu;

    // Quit SDL subsystems
    SDL_Quit();
}

MenuState.h -

#ifndef MENUSTATE_H
#define MENUSTATE_H

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "OptimizedSurface.h"
#include <string>


class MenuState{
    public:
        MenuState();
        virtual ~MenuState();

        bool checkPos( int x, int y );

        SDL_Surface *MenuSurface[ 3 ];

        int buttonX [ 2 ];
        int buttonY [ 2 ];

    protected:

    private:
};

#endif // MENUSTATE_H

MenuState.cpp -

#include "MenuState.h"


MenuState::MenuState(){
    for( int i = 1; i <= 3; ++i){
        this->MenuSurface[ i-1 ] = OptimizedSurface::convert( "assets/menu/" + std::to_string(i) + ".jpg" );
    }
    this->buttonX[ 0 ] = 250;
    this->buttonX[ 1 ] = buttonX[ 0 ] + 140;

    this->buttonY[ 0 ] = 36;
    this->buttonY[ 1 ] = buttonY[ 0 ] + 100;
}

bool MenuState::checkPos( int x, int y ){
    if( this->buttonX[ 0 ] < x && x < this->buttonX[ 1 ] )
        if( this->buttonY[ 0 ] < y && y < this->buttonY[ 1 ] )
            return true;
    return false;
}

MenuState::~MenuState(){
    for( int i = 0; i < 3; ++i ){
        SDL_FreeSurface( this->MenuSurface[ i ] );
        this->MenuSurface[ i ] = nullptr;
    }
}

OptimizedSurface.h -

#ifndef OPTIMIZEDSURFACE_H
#define OPTIMIZEDSURFACE_H

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include "Game.h"
#include <iostream>
#include <stdio.h>


class OptimizedSurface : public Game{
    public:
        OptimizedSurface();
        static SDL_Surface *convert( std::string filepath );
        virtual ~OptimizedSurface();
    protected:
    private:
};

#endif // OPTIMIZEDSURFACE_H

OptimizedSurface.cpp -

#include "OptimizedSurface.h"


OptimizedSurface::OptimizedSurface(){
}

SDL_Surface *OptimizedSurface::convert( std::string filepath ){
    SDL_Surface *optimized_surface = nullptr;
    SDL_Surface *surface = IMG_Load(filepath.c_str());
    if( surface == NULL ){
        printf( "Error Optimizing Surface: %s\n", SDL_GetError() );
    }
    else{
        optimized_surface = SDL_ConvertSurface(surface, windowSurface->format, 0);
        if( optimized_surface == NULL )
            printf( "Error Optimizing Surface: %s\n", SDL_GetError() );
    }
    SDL_FreeSurface(surface);

    return optimized_surface;
}

OptimizedSurface::~OptimizedSurface(){
}

Upvotes: 1

Views: 20555

Answers (1)

Jonny D
Jonny D

Reputation: 2344

If you follow the error message, it says: OptimizedSurface.h|11|error: expected class-name before ‘{’ token

Take a look at OptimizedSurface.h, line 11. You have: class OptimizedSurface : public Game{

There's nothing wrong with that, but the error is saying that the identifier right before the '{' is not recognized. That identifier is Game. So for some reason, Game is not declared before you get to line 11.

Looking at the headers included by OptimizedSurface.h, you probably expect it to be declared in "Game.h". So now look at Game.h. It does indeed have a declaration for the Game class. But before that, there is an #include "MenuState.h". You should guess that this is interfering.

In MenuState.h, you have #include "OptimizedSurface.h"...

Does it make sense yet? It's a circular #include pattern. Your OptimizedSurface needs to know about Game, but Game.h is trying to declare OptimizedSurface (via MenuState.h) first! OptimizedSurface.h depends on Game.h, Game.h depends on MenuState.h, and MenuState.h depends on OptimizedSurface.h.

The best solution is to remove the #include "OptimizedSurface.h" from MenuState.h. MenuState does not actually depend on OptimizedSurface, so there's no need for it. It just contributes to a mess of header dependencies.

If you do have an implementation dependency, then you should #include the appropriate headers in the cpp files. You mentioned that MenuState.cpp depends on OptimizedSurface, so add #include "OptimizedSurface.h" to MenuState.cpp instead of in MenuState.h.

Besides fixing it by removing unnecessary dependencies, you can in some cases solve a circular dependency pattern by adding a "forward declaration" of dependent classes (see a good C++ reference for more). This is important for complicated dependencies, but should not be the solution you use this time.

Upvotes: 20

Related Questions