我知道很多其他关于此的文章,但是我迷失了,因为有太多人说前向声明和其他一些令人困惑的事情,我似乎找不到一种方法来避免在编译器中出现新错误,所以如果有人可以帮助我,将不胜感激。
我在Ubuntu 15.04上使用Code::Blocks
错误是OptimizedSurface.h|11|error: expected class-name before ‘{’ token
我决定在OptimizedSurface header 文件中执行class OptimizedSurface : Game{
,因为在此错误发生之前include/Game.h|18|error: invalid use of member ‘Game::windowSurface’ in static member function
该行已优化_surface = SDL_ConvertSurface(surface,Game::windowSurface-> format,0);
现在,代码是以下文件。
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(){
}
最佳答案
如果您遵循该错误信息,它说:OptimizedSurface.h|11|error: expected class-name before ‘{’ token
看一下OptimizedSurface.h,第11行。class OptimizedSurface : public Game{
没什么错,但是错误是说'{'之前的标识符未被识别。该标识符是Game
。因此由于某种原因,在进入第11行之前就未声明Game
。
查看OptimizedSurface.h包含的 header ,您可能希望它在“Game.h”中声明。现在来看Game.h。它确实有一个Game
类的声明。但在此之前,有一个#include "MenuState.h"
。您应该猜测这会造成干扰。
在MenuState.h中,您具有#include "OptimizedSurface.h"
...
有道理吗?这是一个圆形的#include模式。您的OptimizedSurface
需要了解Game
,但是Game.h尝试首先声明OptimizedSurface
(通过MenuState.h)! OptimizedSurface.h取决于Game.h,Game.h取决于MenuState.h,而MenuState.h取决于OptimizedSurface.h。
最好的解决方案是从MenuState.h中删除#include "OptimizedSurface.h"
。 MenuState实际上并不依赖于OptimizedSurface,因此不需要它。它只是造成头文件依赖的困惑。
如果确实有实现依赖项,则应在cpp文件中#include相应的 header 。您提到MenuState.cpp依赖于OptimizedSurface,因此将#include "OptimizedSurface.h"
添加到MenuState.cpp中,而不是在MenuState.h中。
除了通过消除不必要的依赖关系来解决它之外,在某些情况下,您还可以通过添加依赖类的“正向声明”来解决循环依赖关系模式(有关更多信息,请参见C++引用)。这对于复杂的依赖关系很重要,但不应该是您这次使用的解决方案。