预期 C++ 错误 class-名称在“{”标记之前
C++ error expected class-name before '{' token
我知道很多很多人已经发布了关于这个的帖子,但我很迷茫,因为有这么多人说前瞻性声明和其他非常混乱的事情,我似乎无法找到一种方法来使用而不提出新的我的编译器中的错误,所以如果有人能帮助我,我将不胜感激。
我在 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
线是 optimized_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 行之前未声明 [=12=]。
查看 OptimizedSurface.h 包含的 header,您可能希望它在 "Game.h" 中声明。所以现在看看Game.h。它确实有 Game
class 的声明。但是在之前,还有一个#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,因此不需要它。它只是造成了 header 依赖关系的混乱。
如果您确实有一个 实现 依赖项,那么您应该在 cpp 文件中 #include 适当的 header。您提到 MenuState.cpp 依赖于 OptimizedSurface,因此将 #include "OptimizedSurface.h"
添加到 MenuState.cpp 而不是 MenuState.h.
除了通过删除不必要的依赖来修复它之外,在某些情况下,您还可以通过添加 "forward declaration" 依赖 class 来解决循环依赖模式(有关更多信息,请参见良好的 C++ 参考)。这对于复杂的依赖关系很重要,但不应该是你这次使用的解决方案。
我知道很多很多人已经发布了关于这个的帖子,但我很迷茫,因为有这么多人说前瞻性声明和其他非常混乱的事情,我似乎无法找到一种方法来使用而不提出新的我的编译器中的错误,所以如果有人能帮助我,我将不胜感激。
我在 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
线是 optimized_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 行之前未声明 [=12=]。
查看 OptimizedSurface.h 包含的 header,您可能希望它在 "Game.h" 中声明。所以现在看看Game.h。它确实有 Game
class 的声明。但是在之前,还有一个#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,因此不需要它。它只是造成了 header 依赖关系的混乱。
如果您确实有一个 实现 依赖项,那么您应该在 cpp 文件中 #include 适当的 header。您提到 MenuState.cpp 依赖于 OptimizedSurface,因此将 #include "OptimizedSurface.h"
添加到 MenuState.cpp 而不是 MenuState.h.
除了通过删除不必要的依赖来修复它之外,在某些情况下,您还可以通过添加 "forward declaration" 依赖 class 来解决循环依赖模式(有关更多信息,请参见良好的 C++ 参考)。这对于复杂的依赖关系很重要,但不应该是你这次使用的解决方案。