Eigene Instanz übergeben



  • Die Definition des Typs von *pcGame muss an der Stelle schon bekannt sein. Da fehlt sicher ein #include "whatever.h" .



  • Swordfish schrieb:

    Die Deklaration des Typs von *pcGame muss an der Stelle schon bekannt sein. Da fehlt sicher ein #include "whatever.h" .

    Und genau hier liegt das Problem. Wenn ich das mache, gibt es endlos viele Fehler.

    Ich erstelle ja in der cgame klasse die menu instanz. Und jetzt includiere ich die cgame.hpp in die menu klasse. Irgendetwas geht da total schief.



  • Kompletter Code ... bis auf "endlos viele Fehler" kompilierbares Minimalbeispiel?



  • cgame.hpp

    #include "CGameState_Menu.hpp"
    
    class CGame
    {
    	private:
    		CGameState_Menu cGameState_Menu;
    
    	public:
    		void Initialize ();
    };
    

    cgame.cpp

    #include "CGame.hpp"
    
    void CGame::Initialize ()
    {
    	cGameState_Menu.Initialize (this);
    }
    

    menu.hpp (cgamestate_menu.hpp)

    #include "CGame.hpp"

    class CGame;

    class CGameState_Menu
    {
    private:
    CGame *pcGame;

    public:
    void Initialize (CGame *p_pcGame);
    };

    menu.cpp (cgamestate_menu.cpp)

    #include "CGameState_Menu.hpp"

    void CGameState_Menu::Initialize (CGame *p_pcGame)
    {
    pcGame = p_pcGame;
    }



  • Der Fehler liegt hier:

    menu.hpp

    #include "CGame.hpp"
    
    class CGame;
    
    class CGameState_Menu
    {
    private:
    CGame *pcGame;
    
    public:
    void Initialize (CGame *p_pcGame);
    };
    

    Wenn ich hier CGame.hpp include.



  • cgamestate_menu.hpp

    #ifndef CGAMESTATE_MENU_HPP_INCLUDED
    #define CGAMESTATE_MENU_HPP_INCLUDED
    
    class CGame;
    
    class CGameState_Menu
    {
    private:
    	CGame * pcGame;
    
    public:
    	void Initialize(CGame *p_pcGame);
    };
    
    #endif /* CGAMESTATE_MENU_HPP_INCLUDED */
    

    cgamestate_menu.cpp

    #include "CGameState_Menu.hpp"
    #include "cgame.hpp"
    
    void CGameState_Menu::Initialize(CGame *p_pcGame)
    {
    	pcGame = p_pcGame;
    }
    

    cgame.hpp

    #ifndef CGAME_HPP_INCLUDED
    #define CGAME_HPP_INCLUDED
    
    #include "CGameState_Menu.hpp"
    
    class CGame
    {
    private:
    	CGameState_Menu cGameState_Menu;
    
    public:
    	void Initialize();
    };
    
    #endif /* CGAME_HPP_INCLUDED */
    

    cgame.cpp

    #include "CGame.hpp"
    
    void CGame::Initialize()
    {
    	cGameState_Menu.Initialize(this);
    }
    

    main.cpp

    #include "cgame.hpp"
    
    int main()
    {
    	CGame cgame;
    	cgame.Initialize();
    }
    


  • *edit



  • Sauber, klappt. Vielen Dank! 🙂
    Alter Schwede darauf hätte ich selbst kommen müssen...



  • Eine aller letzte Frage noch...
    Warum genau dort eine Forwärtsdeklaration?

    Das mit dem includen der hpp ist klar, damit es halt definiert ist.
    Aber warum an der Stelle die besagte f.Deklaration?

    Sollte man eigentlich immer f.d. benutzten wenn es geht? oder einfach die Klassen includen?



  • In Zeile 4 von cgamestate_menu.hpp oben? Damit Du in Zeile 9 den Zeiger CGame *pcGame; deklarieren kannst, ohne, daß cgame.hpp eingebunden werden muss, was seinerseits wieder cgamestate_menu.hpp einbinden würde, was seinerseits wieder cgame.hpp einbinden würde, was seinerseits wieder ... ad infinitum.



  • Swordfish schrieb:

    In Zeile 4 von cgamestate_menu.hpp oben? Damit Du in Zeile 9 den Zeiger CGame *pcGame; deklarieren kannst, ohne, daß cgame.hpp eingebunden werden muss, was seinerseits wieder cgamestate_menu.hpp einbinden würde, was seinerseits wieder cgame.hpp einbinden würde, was seinerseits wieder ... ad infinitum.

    Achso. Ok vielen Dank. Dann werde ich jetzt überall f.d. benutzten wo es geht. 🙂



  • Sollte ich eigentlich alle Klassen in der main.cpp includen und dann nur noch mit f.d. arbeiten oder die Klassen dort includen wo sie tatsächlich gebraucht werden?



  • Header da includen so sie gebraucht werden!



  • Schlangenmensch schrieb:

    Header da includen so sie gebraucht werden!

    Und dann mit f.d. arbeiten wo es eben gebrauch wird?



  • Wenn Du nur nen Pointer brauchst tut es eine forward declaration. Brauchst Du eine Instanz, brauchst Du die vollständige Definition.



  • Swordfish schrieb:

    Wenn Du nur nen Pointer brauchst tut es eine forward declaration. Brauchst Du eine Instanz, brauchst Du die vollständige Definition.

    Ja, das stimmt natürlich. Ich weiß nur nicht so genau wann ich includen oder f.d. benutzen soll.

    Also mit den Headers ist jetzt klar. Immer dann includen wenn sie gebraucht werden. Die Frage ist jetzt wann f.d. . Halt immer dann, wenn es gebraucht wird und ein includen des Headers keinen Sinn machen würde?



  • Bizarreofnature schrieb:

    Die Frage ist jetzt wann f.d. . Halt immer dann, wenn es gebraucht wird und ein includen des Headers keinen Sinn machen würde?

    Immer dann, wenn nur der Name des Datentyps gebraucht wird und nicht seine vollständige Definition.

    1. Der vollständige Typ T wird gebraucht, wenn eine Klasse definiert wird, die ein Member vom Typ T oder T[] (C-Style-Array) hat.

    2. Eine Forward-Deklaration genügt, wenn eine Klasse definiert wird, die ein Member vom Typ T&, T* oder std::container<T> hat (container = vector, deque, list, ...).

    3. Eine Forward-Deklaration genügt, wenn Methoden definiert werden, die Parameter oder Rückgabewerte vom Typ T, T*, T& oder std::container<T> haben.

    4. Der vollständige Typ wird gebraucht, wenn von T abgeleitet wird.

    5. Der vollständige Typ wird gebraucht, wenn auf Eigenschaften (Methoden oder Membervariablen) von T zugegriffen wird. Ebenso, wenn Instanzen von T gebildet werden oder wenn sizeof(T) abgefragt wird.

    Die Punkte 1 bis 4 betreffen in der Regel Klassen-Definitionen und damit Header-Dateien. Punkt 5 betrifft die Implementation und kann daher in der Regel in der cpp-Datei erledigt werden, außer bei Templates.

    Die Liste ist bestimmt nicht vollständig.



  • edit



  • Super, vielen Dank 🙂



  • Printe schrieb:

    (Liste, wann includes und forward-decls benutzt werden)

    Schöne Liste. Aber ich gehe meist anders vor:
    1. sicherstellen, dass die .cpp-Datei als allererstes die zugehörige .h-Datei includet
    2. keine unnützen Header einbinden
    3. Mit forward-Dekl. gehe ich sparsam um und verwende die eigentlich nur, wenn es sich lohnt. Sofern Compilezeit kein großes Problem ist, einfach die passende .h einbinden und forward-Dekl. nur sparsam bzw. für zirkuläre Bezüge, von denen es hoffentlich nur wenige/keine gibt, nutzen.
    4. Wenn man häufiger merkt, dass man eigentlich nur diverse Fwd-Dekl. aus einem bestimmten Bereich braucht, ggf. einen whatever_fwd.h -Header erzeugen, der ne gesammelte Liste nur mit den entsprechenden Forward-Deklarationen enthält.

    Ich finde nämlich, dass

    namspace foo {
    namespace bar {
    class Baz;
    } // namespace bar
    } // namespace foo
    

    sehr viel umständlicher zu lesen ist als

    #include "foo/bar/Baz.h"
    

    oder auch

    #include "foo/bar_fwd.h"
    

    Wenn man viele Forwards macht, kann man auch leicht mal die Übersicht verlieren, wenn z.B. eine Klasse in einen anderen Namespace verschoben wird.


Anmelden zum Antworten