Reputation: 5075
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
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