Eigene Instanz übergeben



  • Hallo!

    Ich habe 2 Klassen. In Klasse 1 ist Klasse 2 definiert (die Instanz von Klasse 2 wird in Klasse 1 erstellt). Jetzt will ich die "eigene" (Klasse 1) Instanz an Klasse 2 übergeben. Ich weiß aber leider nicht wie. Ich habs schon mit "this" probiert.

    Danke schonmal!
    MfG Bizarreofnature



  • Also erstmal riecht das immer ein bisschen nach Designfehler was du da vor hast. Gibt natürlich Fälle wo es OK ist, aber denk vielleicht nochmal drüber nach.

    Ansonsten - was hat denn beim Versuch "this" zu verwenden nicht funktioniert? Macht dich die Warning nervös die dir der Compiler dabei gibt? Der Grund für die Warning ist, dass man bevor der Konstruktor fertig gelaufen ist noch gar kein fertiges "Klasse 1" Objekt hat, d.h. man übergibt einen Zeiger auf ein Objekt das genaugenommen noch gar nicht existiert. Je nachdem was "Klasse 2" in ihrem Konstruktor dann damit macht kann das OK sein oder halt auch nicht. Um das zu beurteilen müsstest du uns schon Code zeigen. Idealerweise nicht "anonymisiert" mit "Klasse 1" und "Klasse 2", sondern mit den Namen die du in deinem Code hast - dann kann man sich normalerweise leichter vorstellen was du da überhaupt versuchst zu machen.



  • Ok.

    Vorweg, ich benutzte keine Konstruktoren.

    Jetzt erstmal was zum Design:

    In "CGame" erstelle ich die Instanz "CGameState_Menu" und CGameState_Game.

    Das ganze etwas abekürzt:

    CGame.hpp:

    // classes
    ...
    #include "CGameState_Menu.hpp"
    
    // CGame class: manages the game itself
    class CGame
    {
    	private:
    		...
    
    		// create instance of CGameState_Menu class
    		CGameState_Menu cGameState_Menu;
    
    	public:
    		// initialize instace of CGame
    		void Initialize (CFramework &p_cFramework);
    
    };
    

    CGame.cpp: (hier will ich die Instanz mit this übergeben)

    void CGame::Initialize (CFramework &p_cFramework)
    {
    	// initialize cGameState_Menu
    	cGameState_Menu.Initialize (*this, p_cFramework, cSprite, cFont, cAudio, cHighscore, cBackground);
    }
    

    CGameState_Menu.hpp:

    // classes
    #include "CGame.hpp"
    
    // CGameState_Menu class: the main menu
    class CGameState_Menu
    {
    	private:
    		// cGame access
    		CGame *pcGame;
    
    	public:
    		// initialize instace of CGameState_Menu
    		void Initialize (CGame &p_cGame, CFramework &p_cFramework, CSprite &p_cSprite, CFont &p_cFont, CAudio &p_cAudio, CHighscore &p_cHighscore, CBackground &p_cBackground);
    };
    

    CGameState_Menu.cpp:

    void CGameState_Menu::Initialize (CGame &p_cGame, CFramework &p_cFramework, CSprite &p_cSprite, CFont &p_cFont, CAudio &p_cAudio, CHighscore &p_cHighscore, CBackground &p_cBackground)
    {
    	// cGame access
    	pcGame = &p_cGame;
    }
    


  • Sorry ich hab gerade Schwierigkeiten mit dem Code hier...



  • Bizarreofnature schrieb:

    Vorweg, ich benutzte keine Konstruktoren

    Warum?



  • Wie wäre es mit einer Fehlermeldung oder Beispielcode den man durch einen Compiler jagen kann, um dein Problem zu verstehen?

    Möglicherweise suchst du nach dem Begriff "Forward Declaration" bzw. "Vorwärtsdeklaration". Klassen die gegenseitig voneinander abhängig sind, sind i.d.R. aber kein besonders robustes Klassendesign...



  • Stichwort dazu: Cross-Include



  • Du solltest aufhören, Referenzen zu übergeben, wenn es sich in Wahrheit um Pointer handelt.

    Es ist schon klar, dass deine Klassenmember keine Referenzen sein können, wenn du keine Konstruktoren verwendest. Aber dann sei so ehrlich und deklarier die Pointer auch offen.

    Hier ist ein Stück Code, das funktioniert:

    class Game;
    class GameState_Menu;
    class Framework;
    
    class GameState_Menu
    {
    	Game * game;
    
    public:
    
    	void Initialize (Game * game_) 
    	{
    		game = game_;
    	}
    };
    
    class Game
    {
    	Framework * framework;
    	GameState_Menu menu;
    
    public:
    
    	void Initialize (Framework * framework_)
    	{
    		framework = framework_;
    
    		menu.Initialize (this);
    	}
    };
    
    int main ()
    {
    	Framework * framework = 0; // create framework instance here
    
    	Game game;
    	game.Initialize (framework);
    
    	return 0;
    }
    

    Ich hasse geprefixte Bezeichner ... 😉



  • Danke erstmal für all die Antworten.
    Ich konnte einiges mitnehmen.

    Es ist und bleibt ein Designfehler.
    Da kann man nichts machen, außer das Design ändern 🙂

    Wie gesagt, vielen Dank.



  • Aber eine Frage hätte ich dennoch...

    Soweit hat alles geklappt. Ich habe die eigene Instanz mit "this" übergeben.
    Wenn ich jetzt z.B.:

    pcGame->irgendetwas
    

    mache, gibt er folgendes aus:

    Der Klassentyp "pointer-to-incomplete" ist nicht zulässig.



  • 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.