Klasse für Menüitems - Error C4430



  • Du brauchst in Game.h doch nur

    #include <memory>
    #include <SFML/Graphics.hpp>
    #include "Gamestate.h"



  • Nur das includieren, was der Header (!) zum Übersetzen braucht.
    Im einzelnen:
    MainMenuState.h ist ok so, forward declarations würden zu weit führen.
    MenuItem.h braucht kein Game.h, es braucht nur den Graphics Header von SFML (BTW: Kein using namespace in Headerdateien, böse!)
    Game.h braucht kein iostream und kein MainMenuState.h.



  • In .cpp-Dateien kann man praktisch inkludieren, was man will, solange man .cpp-Dateien niemals in andere .cpp-Dateien (oder gar in .h-Dateien) inkludiert. So entstehen keine zyklischen includes.

    Kniffliger ist die Sache mit .h-Dateien, denn die sollen (und werden) in andere inkludiert.

    Hier muß man das beachten, was Nathan schreibt - indem man sich vorstellt, wie der Textstrom aus dem Präprozessor herauskommt und was demnach der Compiler zu sehen bekommt.
    (- lernen zu denken wie ein Compiler ist ja sowieso keine schlechte Idee, wenn man C++ programmiert)

    ich vermeide zyklische Includes durch das Prinzip "nach einer Seite includieren, nach der anderen Seite deklarieren" - d.h. wenn A von B abhängt und B von A, dann schreibe ich in A.h "#include B.h" und in B.h
    "class A;"



  • Nathan schrieb:

    Nur das includieren, was der Header (!) zum Übersetzen braucht.
    Im einzelnen:
    MainMenuState.h ist ok so, forward declarations würden zu weit führen.
    MenuItem.h braucht kein Game.h, es braucht nur den Graphics Header von SFML (BTW: Kein using namespace in Headerdateien, böse!)
    Game.h braucht kein iostream und kein MainMenuState.h.

    Ich habe in MenuItem.h doch zwei Funktionen, die einen Parameter vom Typ Game haben, also muss ich doch Game includen?

    bool checkIfHovered(Game& game);
    void draw(Game& game);
    

    Ohne das using namespace schmeißt mir Visual Studio aber Errors ohne Ende bei den strings entgegen, wie kann ich das denn umgehen?

    Danke für die Hilfe! 🙂



  • Sorry hab die zwei nicht gesehen. Dann behalt das include. Oder informiere dich über forward declarations, dann brauchst du das auch nicht.
    Zum Namespace: Dann machst du dasselbe wie mit dem Namespace von SFML, der heißt sf und die Elemente daraus prefixest du mit sf::, bei der Standardibliothek heißt der Namespace std und die Elemente prefixest du dann entsprechend mit std::.



  • Super, vielen Dank! Die ursprünglichen Fehler sind damit behoben.

    Also kann ich mir grundsätzlich merken:

    • So wenige includes in headern wie möglich
    • Bei .cpp Datein sind die includes nicht so entscheidend (dürfen auch mal zuviele sein)
    • Kein using namespace in headern

    2 Fehler habe ich aber noch, die haben allerdings nicht umbedingt etwas mit den Ursprungsfehlern zu tun:

    Error 2 error LNK2019: unresolved external symbol "public: __thiscall MenuItem::~MenuItem(void)" (??1MenuItem@@QAE@XZ) referenced in function __unwindfunclet$??0MainMenuState@@QAE@XZ$4 C:\Users\Michel\Documents\Visual Studio 2013\Projects\SFML Test\SFML Test\MainMenuState.obj Action Snake

    Error 3 error LNK1120: 1 unresolved externals C:\Users\Michel\Documents\Visual Studio 2013\Projects\SFML Test\Debug\Action Snake.exe Action Snake

    Die .cpp Datei der MainMenuState Klasse sieht folgendermaßen aus:

    #include "MainMenuState.h"
    #include <iostream>
    
    MainMenuState::MainMenuState()
    :singlePlayer("Singleplayer", font, 45, 500.f, 350.f),
    localMultiPlayer("Local Multiplayer", font, 45, 500.f, 400.f),
    quitGame("Quit Game", font, 45, 500.f, 450.f)
    {
    	//Load font and menu item text
    	font.loadFromFile("assets\\fnt\\calibri.ttf");	
    
    }
    
    void MainMenuState::HandleEvents(Game& game)
    {
    	//Handle all events
    	sf::Event event;
    
    	while (game.window.pollEvent(event))
    	{
    		if (event.type == sf::Event::Closed)
    		{
    			game.window.close();
    			game.running = false;
    		}
    	}
    }
    
    void MainMenuState::Update(Game& game)
    {
    	//Check if mouse is over menu item
    	bSinglePlayerSelected = singlePlayer.checkIfHovered(game);
    	bLocalMultiPlayerSelected = localMultiPlayer.checkIfHovered(game);
    	bQuitGameSelected = quitGame.checkIfHovered(game);
    
    }
    
    void MainMenuState::Draw(Game& game)
    {
    	//Renders the scene
    	singlePlayer.draw(game);
    	localMultiPlayer.draw(game);
    	quitGame.draw(game);
    
    }
    
    MainMenuState::~MainMenuState()
    {
    	//Destruktor of the class
    	std::cout << "Menudestruktor wurde aufgerufen!" << std::endl;
    }
    


  • Smofe schrieb:

    • So wenige includes in headern wie möglich
    • Bei .cpp Datein sind die includes nicht so entscheidend (dürfen auch mal zuviele sein)
    • Kein using namespace in headern

    Ja, das ist soweit richtig. Zu viele includes in cpp sind natürlich auch nicht so schön, schaden aber auch nicht sonderlich (insbesondere nicht bei Projekten deiner Größe).

    2 Fehler habe ich aber noch, die haben allerdings nicht umbedingt etwas mit den Ursprungsfehlern zu tun:

    Error 2 error LNK2019: unresolved external symbol "public: __thiscall MenuItem::~MenuItem(void)" (??1MenuItem@@QAE@XZ) referenced in function __unwindfunclet$??0MainMenuState@@QAE@XZ$4 C:\Users\Michel\Documents\Visual Studio 2013\Projects\SFML Test\SFML Test\MainMenuState.obj Action Snake

    Error 3 error LNK1120: 1 unresolved externals C:\Users\Michel\Documents\Visual Studio 2013\Projects\SFML Test\Debug\Action Snake.exe Action Snake

    Irgendwas mit "unresolved external symbol" oder "undefined reference" heißt immer: du hast eine Funktion deklariert, aber nirgends definiert. In diesem Fall ist das der Destruktor der MenuItem Klasse. Da du in den Destruktoren aber eh nur (unnötige) Logausgaben machst, kannst du die auch weglassen.

    Nur so aus Neugier: Kannst du mal das Tutorial verlinken, das scheint richtig gut zu sein, dass es dir std::unique_ptr beibringst.

    Zum weiteren Lernen von C++: Da du scheinbar schon Erfahrungen im Programmieren hast, ist The C++ Programming Language vom Erfinder der Sprache selber oft empfohlen werden:
    The C++ Programming Language | ISBN: 9780321563842
    Ich selber kenne es nicht, aber es soll die grundlegenden Grundlagen nicht detailliert behandlen, sondern eher die Sprache C++ vorstellen.



  • Schau dir mal nebenbei die SFML Engine von den Entwiklern an. Der Code ist aus dem Buch: http://www.amazon.de/SFML-Game-Development-Jan-Haller/dp/1849696845

    Code: https://github.com/LaurentGomila/SFML-Game-Development-Book


  • Mod

    In deinem Eröffnungsbeitrag wird in Zeile 14 ein selbstgeschriebener Destruktor deklariert. Den implementierst du aber anscheinend nirgendwo (oder an einem Ort, den der Linker nicht finden kann). Brauchst du überhaupt einen selbstgeschriebenen Destruktor? Falls ja, wäre deine Klasse höchstwahrscheinlich unvollständig, da du dann die Regel der großen Drei verletzen würdest. Das sieht mir doch eher danach aus, als würde der compilergenerierte Destruktor vollständig ausreichen (wie es normal ist) und du kannst dir die Deklaration einfach komplett sparen.

    Das gleiche gilt höchstwahrscheinlich auch für den selbstgeschriebenen Standardkonstruktor in der Zeile davor, bloß rufst du diesen anscheinend sowieso nirgendwo auf.

    Wenn dir irgendein Lehrbuch beigebracht haben sollte, dass du immer eigene Destruktoren und Standardkonstruktoren schreiben solltest, selbst wenn diese dann leer sind: Ein Fall fürs Altpapier.



  • Ja, es lag tatsächlich an dem Destruktor.

    Vielen Dank! Ihr habt mir wirklich sehr geholfen. Ich werde mir die beiden Bücher mal angucken, vielleicht befindet sich ja auch eins davon in der Bücherei vorort 🙂

    Ein Lehrbuch hat mir hier nichts beigebracht - das war ja auch das Problem. Jetzt klappt jedenfalls alles! 🙂

    Einen schönen Abend noch.

    Edit: Die Konstruktoren sind alle mit Code befüllt - nur der Destruktor war leer 🙂


Anmelden zum Antworten