invalid use of incomplete type / forward declaration



  • Hallo ihr Lieben,
    Ich bekomme folgenden error:

    error: invalid use of incomplete type ‘class StateMachine’
      while(sm.window.isOpen())
    note: forward declaration of ‘class StateMachine’
     class StateMachine;
    

    Einigen Beiträgen zufolge könnte das an falschem Includieren oder einer Includier-Schleife liegen, allerdings werde ich daraus nicht schlau, was ich ändern soll. Im allgemeinen, wenn Klasse X Klasse Y includiert, die main aber auch beide includiert, sollte es doch eine doppelte Definition der Klassen geben. Allerdings includiere ich ja auch mehrmals SFML, was ja funktioniert, obwohl diese wiederum includiert werden. Warum?
    State.h:

    #pragma once
    #include <SFML/Graphics.hpp>
    
    class StateMachine;
    
    class State
    {
    public:
    	virtual ~State() {};
    	virtual void handleEvents(StateMachine &sm) = 0;
    	virtual void update(StateMachine &sm) = 0;
    	virtual void draw(StateMachine &sm) = 0;
    };
    

    StateMachine.h:

    #include <SFML/Graphics.hpp>
    #include "MainMenuState.h"
    
    class StateMachine
    {
    	sf::RenderWindow window;
    	bool running;
    	MainMenuState *currentState;
    	
    public:
    	StateMachine();
    	void run();
    };
    

    StateMachine.cpp:

    #include "StateMachine.h"
    
    StateMachine::StateMachine()
    {
    	currentState = new MainMenuState();	
    	
    	std::vector<sf::VideoMode> modes = sf::VideoMode::getFullscreenModes();
    	window.create(sf::VideoMode(modes[0].width, modes[0].height, modes[0].bitsPerPixel), "SFML window", sf::Style::Fullscreen);
    	running = true;
    }
    
    void StateMachine::run()
    {
    	while(running)
    	{
    	
    		currentState->handleEvents(*this);
    		
    		currentState->update(*this);
    		
    		currentState->draw(*this);
    	
    	}
    	
    }
    

    MainMenuState.h:

    #pragma once
    #include "State.h"
    
    
    class MainMenuState : public State
    {
    private:
    	sf::Font font;	
    		
    public:
    	MainMenuState();
    	~MainMenuState();
    	void handleEvents(StateMachine &sm);
    	void update(StateMachine &sm);
    	void draw(StateMachine &sm);
    };
    

    MainMenuState.cpp:

    #include "MainMenuState.h"
    
    MainMenuState::MainMenuState()
    {
    	font.loadFromFile("fonts/Short Baby.ttf");
    }
    
    MainMenuState::~MainMenuState()
    {
    
    
    }
    
    void MainMenuState::handleEvents(StateMachine &sm)
    {
    	while(sm.window.isOpen())
    	{}
    
    }
    
    void MainMenuState::update(StateMachine &sm)
    {
    
    
    }
    
    void MainMenuState::draw(StateMachine &sm)
    {
    
    
    }
    

    main.cpp:

    #include "StateMachine.h"
    
    int main()
    {
    	StateMachine sm;
    	sm.run();
    	return 0;
    }
    


  • Der den Fehler hervorrufende Code

    @daniel sagte in invalid use of incomplete type / forward declaration:

    while(sm.window.isOpen())
    

    ist in keiner der von Dir geposteten Dateien zu finden. Poste bitte ein kompilierbares Minimalbeispiel. (Dazu brauchst Du kein sfml.)

    Aber ich kann Dir sagen, daß in der .cpp in der og. Code steht ein

    #include "StateMachine.h"
    

    fehlt.

    PS:

    @daniel sagte in invalid use of incomplete type / forward declaration:

    currentState = new MainMenuState();

    Warum new?



  • @Swordfish Ups, ich habe eine andere Version von MainMenuState.cpp reinkopiert; ist jetzt berichtigt. Mit new erstelle ich das Objekt doch auf dem Heap, muss also das löschen explizit aufrufen. Und ich möchte das löschen nicht durch das Ende eines bereiches hervorrufen. Ist das so richtig? Wenn ich #include "StateMachine.h" in den State Header schreibe, erscheinen noch viel mehr Fehler
    Minimalbeispiel:
    Main.cpp:

    #include "StateMachine.h"
    
    int main()
    {
    	StateMachine sm;
    	sm.run();
    	return 0;
    }
    

    MainMenuState.cpp:

    #include "MainMenuState.h"
    
    void MainMenuState::handleEvents(StateMachine &sm)
    {
    	
    }
    

    MainMenuState.h:

    #pragma once
    #include "State.h"
    
    
    class MainMenuState : public State
    {
    public:
    	void handleEvents(StateMachine &sm);
    };
    

    State.h:

    #pragma once
    
    class StateMachine;
    
    class State
    {
    public:
    	virtual void handleEvents(StateMachine &sm) = 0;
    };
    

    StateMachine.h:

    #include "MainMenuState.h"
    
    class StateMachine
    {
    	MainMenuState *currentState;
    public:
    	StateMachine();
    	void run();
    };
    

    StateMachine.cpp:

    #include "StateMachine.h"
    
    StateMachine::StateMachine()
    {
    	currentState = new MainMenuState();	
    }
    
    void StateMachine::run()
    {
    	currentState->handleEvents(*this);
    }
    


  • @daniel

    Wenn ich #include "StateMachine.h" in den State Header schreibe, erscheinen noch viel mehr Fehler

    Dann behebe die Fehler.

    MainMenuState *currentState; Warum ist das nicht State*?



  • This post is deleted!


  • @manni66 Hab es geändert; so sehen die Fehlermeldungen aus:

    StateMachine.h:6:2: error: ‘State’ does not name a type; did you mean ‘static’?
      State *currentState;
      ^~~~~
      static
    In file included from main.cpp:1:0:
    StateMachine.h:4:7: error: redefinition of ‘class StateMachine’
     class StateMachine
           ^~~~~~~~~~~~
    In file included from State.h:2:0,
                     from MainMenuState.h:2,
                     from StateMachine.h:1,
                     from main.cpp:1:
    StateMachine.h:4:7: note: previous definition of ‘class StateMachine’
     class StateMachine
           ^~~~~~~~~~~~
    In file included from State.h:2:0,
                     from MainMenuState.h:2,
                     from StateMachine.h:1,
                     from StateMachine.cpp:1:
    StateMachine.h:6:2: error: ‘State’ does not name a type; did you mean ‘static’?
      State *currentState;
      ^~~~~
      static
    In file included from StateMachine.cpp:1:0:
    StateMachine.h:4:7: error: redefinition of ‘class StateMachine’
     class StateMachine
           ^~~~~~~~~~~~
    In file included from State.h:2:0,
                     from MainMenuState.h:2,
                     from StateMachine.h:1,
                     from StateMachine.cpp:1:
    StateMachine.h:4:7: note: previous definition of ‘class StateMachine’
     class StateMachine
           ^~~~~~~~~~~~
    StateMachine.cpp: In constructor ‘StateMachine::StateMachine()’:
    StateMachine.cpp:5:2: error: ‘currentState’ was not declared in this scope
      currentState = new MainMenuState();
      ^~~~~~~~~~~~
    StateMachine.cpp:5:2: note: suggested alternative: ‘MainMenuState’
      currentState = new MainMenuState();
      ^~~~~~~~~~~~
      MainMenuState
    StateMachine.cpp: In member function ‘void StateMachine::run()’:
    StateMachine.cpp:10:2: error: ‘currentState’ was not declared in this scope
      currentState->handleEvents(*this);
      ^~~~~~~~~~~~
    StateMachine.cpp:10:2: note: suggested alternative: ‘MainMenuState’
      currentState->handleEvents(*this);
      ^~~~~~~~~~~~
      MainMenuState
    In file included from State.h:2:0,
                     from MainMenuState.h:2,
                     from MainMenuState.cpp:1:
    StateMachine.h:6:2: error: ‘State’ does not name a type; did you mean ‘static’?
      State *currentState;
      ^~~~~
      static
    


    1. in StaeMachine.h fehlt das pragma once

    2. In file included from State.h:2:0,
      from MainMenuState.h:2,
      from StateMachine.h:1,
      from main.cpp:1:

    Wozu braucht StateMachin.h MainMenuState.h? Für State* reicht eine simple Vorwärtsdeklaration.



  • @daniel sagte in invalid use of incomplete type / forward declaration:

    currentState = new MainMenuState();	
    

    Warum new?

    @daniel sagte in invalid use of incomplete type / forward declaration:

    Mit new erstelle ich das Objekt doch auf dem Heap, muss also das löschen explizit aufrufen.

    Selbst wenn. Das macht man schon seit Jahren nicht mehr so. RAII, Smartpointer.

    @daniel sagte in invalid use of incomplete type / forward declaration:

    Und ich möchte das löschen nicht durch das Ende eines bereiches hervorrufen. Ist das so richtig?

    Ja, Jein, Nein. Welcher Bereich? Meinst Du Scope (also Block, etwas zwischen { und }? Wenn ja, welchen Scope hat denn Dein currentState?



  • @manni66 Weil die StateMachine alle möglichen States braucht. Also MainMenuState und später auch GameState usw



  • @Swordfish Ja ich habe smartpointer gesehen aber ich möchte erstmal mit den Pointern völlig klarkommen, bevor ich damit anfange.



  • @daniel sagte in invalid use of incomplete type / forward declaration:

    @manni66 Weil die StateMachine alle möglichen States braucht. Also MainMenuState und später auch GameState usw

    Auf welche Frage von @manni66 ist das die Antwort?



  • @daniel sagte in invalid use of incomplete type / forward declaration:

    @manni66 Weil die StateMachine alle möglichen States braucht. Also MainMenuState und später auch GameState usw

    Im Header?



  • @daniel sagte in invalid use of incomplete type / forward declaration:

    ich möchte erstmal mit den Pointern völlig klarkommen

    Kommst du nicht. Deswegen gibt es Smartpointer.



  • This post is deleted!


  • @Swordfish auf die Zweite
    @manni66 stimmt, nur in der implementierung
    @manni66 Okay aber ein Smartpointer ist doch nur ein Pointer mit automatisierter Garbage collection oder? Wie sähe eine implementierung davon in diesem Beispiel aus?



  • @daniel sagte in invalid use of incomplete type / forward declaration:

    nur ein Pointer mit automatisierter Garbage collection oder?

    Nein. Aber selbst wenn es so wäre: was möchtest du damit sagen?



  • @manni66 War eher eine Frage.
    Also das ist jetzt die StateMachine.h mit smartpointer:

    #pragma once
    #include "MainMenuState.h"
    #include <memory>
    #include "State.h"
    
    class StateMachine
    {
    private:
    	std::unique_ptr<State> currentState;
    public:
    	StateMachine();
    	void run();
    
    

    StateMachine.cpp:

    #include "StateMachine.h"
    
    StateMachine::StateMachine()
    {
    	currentState = std::move(std::unique_ptr<MainMenuState>(new MainMenuState));
    }
    
    void StateMachine::run()
    {
    	currentState->handleEvents(*this);
    }
    

    Und State.h, welche StateMachine includiert

    #pragma once
    #include "StateMachine.h"
    
    class State
    {
    public:
    	virtual void handleEvents(StateMachine &sm) = 0;
    };
    

    Das ergibt allerdings wieder folgende Fehler:

    In file included from MainMenuState.h:2:0,
                     from StateMachine.h:2,
                     from main.cpp:1:
    State.h:7:28: error: ‘StateMachine’ has not been declared
      virtual void handleEvents(StateMachine &sm) = 0;
                                ^~~~~~~~~~~~
    In file included from StateMachine.h:2:0,
                     from main.cpp:1:
    MainMenuState.h:8:20: error: ‘StateMachine’ has not been declared
      void handleEvents(StateMachine &sm);
                        ^~~~~~~~~~~~
    In file included from MainMenuState.h:2:0,
                     from StateMachine.h:2,
                     from StateMachine.cpp:1:
    State.h:7:28: error: ‘StateMachine’ has not been declared
      virtual void handleEvents(StateMachine &sm) = 0;
                                ^~~~~~~~~~~~
    In file included from StateMachine.h:2:0,
                     from StateMachine.cpp:1:
    MainMenuState.h:8:20: error: ‘StateMachine’ has not been declared
      void handleEvents(StateMachine &sm);
                        ^~~~~~~~~~~~
    StateMachine.cpp: In member function ‘void StateMachine::run()’:
    StateMachine.cpp:10:34: error: no matching function for call to ‘State::handleEvents(StateMachine&)’
      currentState->handleEvents(*this);
                                      ^
    In file included from MainMenuState.h:2:0,
                     from StateMachine.h:2,
                     from StateMachine.cpp:1:
    State.h:7:15: note: candidate: virtual void State::handleEvents(int&)
      virtual void handleEvents(StateMachine &sm) = 0;
                   ^~~~~~~~~~~~
    State.h:7:15: note:   no known conversion for argument 1 from ‘StateMachine’ to ‘int&’
    In file included from State.h:2:0,
                     from MainMenuState.h:2,
                     from MainMenuState.cpp:1:
    StateMachine.h:9:18: error: ‘State’ was not declared in this scope
      std::unique_ptr<State> currentState;
                      ^~~~~
    StateMachine.h:9:18: note: suggested alternative: ‘getdate’
      std::unique_ptr<State> currentState;
                      ^~~~~
                      getdate
    StateMachine.h:9:23: error: template argument 1 is invalid
      std::unique_ptr<State> currentState;
                           ^
    StateMachine.h:9:23: error: template argument 2 is invalid
    
    

    Habe ich vieleicht eine Falsche herangehensweise? Könnt ihr mir vieleicht ein extrem vereinfachtes Beispiel für eine StateMachine zeigen?



  • Auch für Referenzen reicht eine Vorwärtsdeklaration. Entferne das include StateMachine aus dem State Header.



  • #include "MainMenuState.h" warum steht das immer noch im Header?



  • Okay hab das gemacht und es funktioniert alles. Vielen Dank!


Log in to reply