C++错误期望'{'标记之前的类名

Chr*_*e55 0 c++ sdl compiler-errors derived-class

我知道很多,其他很多人已经发布了这个但是我很迷茫,因为有很多人说前向声明和其他大量令人困惑的东西我似乎无法找到一种方法来使用而不会在我的编译器中出现新的错误所以如果有人能帮助我,将非常感激.

我在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 该行是optimize_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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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(){
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*y D 11

如果您按照错误消息,它说: OptimizedSurface.h|11|error: expected class-name before ‘{’ token

看一下第11行的OptimizedSurface.h.你有: class OptimizedSurface : public Game{

这没有什么不对,但错误是说'{'之前的标识符无法识别.那个标识符是Game.所以出于某种原因,Game在你到达第11行之前没有宣布.

查看OptimizedSurface.h包含的头文件,您可能希望在"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.

最好的解决方案是#include "OptimizedSurface.h"从MenuState.h中删除它.MenuState实际上并不依赖于OptimizedSurface,因此不需要它.它只会造成一堆乱七八糟的依赖关系.

如果您确实有实现依赖项,那么您应该#include cpp文件中的相应头文件.您提到MenuState.cpp依赖于OptimizedSurface,因此添加#include "OptimizedSurface.h"到MenuState.cpp而不是MenuState.h.

除了通过删除不必要的依赖项来修复它之外,在某些情况下,您可以通过添加依赖类的"前向声明"来解决循环依赖模式(有关更多信息,请参阅优秀的C++参考).这对于复杂的依赖项很重要,但不应该是您这次使用的解决方案.