invalid use of incomplete type / forward declaration
-
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*?
-
Dieser Beitrag wurde gelöscht!
-
@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
-
-
in StaeMachine.h fehlt das pragma once
-
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 DeincurrentState
?
-
@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.
-
Dieser Beitrag wurde gelöscht!
-
@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!
-
@daniel sagte in invalid use of incomplete type / forward declaration:
Wie sähe eine implementierung davon in diesem Beispiel aus?
context.h
#pragma once #include <memory> struct context_t { virtual void present() const = 0; virtual std::unique_ptr<context_t> handle_input() = 0; virtual ~context_t() = default; };
title_screen_context.h
#pragma once #include "context.h" struct title_screen_context_t final : context_t { virtual void present() const override; virtual std::unique_ptr<context_t> handle_input() override; };
title_screen_context.cpp
#include "title_screen_context.h" #include "main_menu_context.h" #include <iostream> void title_screen_context_t::present() const { std::cout << "title screen\n\npress enter\n\n"; } std::unique_ptr<context_t> title_screen_context_t::handle_input() { std::cin.get(); return std::make_unique<main_menu_context_t>(); }
main_menu_context.h
#pragma once #include "context.h" struct main_menu_context_t final : context_t { virtual void present() const override; virtual std::unique_ptr<context_t> handle_input() override; };
main_menu_context.cpp
#include "main_menu_context.h" #include "credits_context.h" #include <iostream> void main_menu_context_t::present() const { std::cout << "[1] menu item 1\n[2] menu item 2\n[3] menu item 3\n[0] exit\n"; } std::unique_ptr<context_t> main_menu_context_t::handle_input() { int choice; std::cin >> choice; switch (choice) { case 0: return std::make_unique<credits_context_t>(); case 1: return std::make_unique<main_menu_context_t>(); // todo: context fuer menuepunkt 1 case 2: return std::make_unique<main_menu_context_t>(); // todo: context fuer menuepunkt 2 case 3: return std::make_unique<main_menu_context_t>(); // todo: context fuer menuepunkt 3 } return std::make_unique<main_menu_context_t>(); }
credits_context.h
#pragma once #include "context.h" struct credits_context_t final : context_t { virtual void present() const override; virtual std::unique_ptr<context_t> handle_input() override; };
credits_context.cpp
#include "credits_context.h" #include "main_menu_context.h" #include <iostream> void credits_context_t::present() const { std::cout << "Credits: ...\n\nReally Exit? [y|n]\n"; } std::unique_ptr<context_t> credits_context_t::handle_input() { char choice; std::cin >> choice; if (choice == 'y') return nullptr; return std::make_unique<main_menu_context_t>(); }
machine.h
#pragma once #include <memory> #include "title_screen_context.h" struct machine_t final { std::unique_ptr<context_t> context = std::make_unique<title_screen_context_t>(); void run(); };
machine.cpp
#include "machine.h" void machine_t::run() { while (context) { context->present(); context.reset(context->handle_input().release()); } }
main.cpp
#include "machine.h" int main() { machine_t{}.run(); }
-
@Swordfish Oh wow danke, damit muss ich mich jetzt erstmal beschäftigen
-
= default
Das macht die struct trivial glaube ich, warum benutzt du das?
context.reset(context->handle_input().release());
Was genau macht diese Zeile?