Auf Variablen von Objekten zugreifen



  • Wow danke euch für die schnellen Antworten !
    Stichwort friend class ist sehr hilfreich ^^

    Ok ich versuche einmal zusammen zu fassen (und weil ich ganz dreist bin mach ich das anhand Bsp.2 von fr33g ^^) :

    Ok ich habe in der Klasse "player" alle Variablen unter private und map als Freund. *check*

    In der Klasse "map". mal sehen ob ich das verstanden habe:

    GetX() const { return pl.GetX(); }
    

    Bedeutet ich habe eine "Funktion"(ich weiss es heisst anders aber mir fällt zu dieser späten Stunde der richtige Ausdruck nicht ein, sry) die ich aufrufen kann und mir X zurückgibt ...

    SetX( int x_ ) { pl.x = x_; }
    

    Während das hier eine "Funktion" die int x_ and pl.x schikt.
    Und Player& pl habe ich nach herumprobieren heraus gefunden sagt wo sich pl versteckt hält.

    So weit so gut aber hier meine map.h:

    #include <hge.h>
    #include <hgeSprite.h>
    
    class map
    { 
    
      private:   
      hgeSprite *maps;
      HTEXTURE maptex;
      int tile[8][6];
      player& pl;
    
      public:
      void update();
      void render(HGE *hge);
      void start(HGE *hge); 
      float GetX() const { return pl.xn; } 
    
    };
    

    Es wird mir immer
    "9 C:\...\main.cpp structure `map1' with uninitialized reference members " als Fehlermeldung beim Kompilieren ausgegeben. Ich bin irgendwie Ratlos.

    Danke nochmal für die fixen Antworten!

    Lg Veyl



  • Also mit

    int GetX() const { return pl.GetX(); }
    

    greifst du auf die Schnittstelle von Player zu, welche dann eben die private Membervariable x zurückgibt.
    Mit

    void SetX( int x_ ) { pl.x = X_; }
    

    greifst du eben direkt auf die private Membervariable zu, ohne die Schnittstelle der Klasse Player zu nutzen da du ja der Freund bist.

    Mit deinem Fehler, ich glaube das liegt nicht an dem Codefetzen sondern wo anderster, gib mal bisschen mehr Code 😉

    Lg freeG



  • Ich würd den player jetzt nicht als private member Referenz in der Klasse angeben. Kann ja sein, dass du mal mehrere Player hast? Oder auch andere Dinge (Monster?) die von der Player-Klasse abgeleitet sind (oder umgekehrt). Dann müsstest du jedesmal eine SetPlayer() Funktion deines Map-Objekts aufrufen bevor du was damit anfangen kannst.

    In dem Fall würde ich Player einfach als Parameter übergeben

    class Map
    {
    public:
    GetX(Player &pl) const { return pl.GetX(); }
    SetX(Player &pl, int x_ ) { pl.SetX( x_ ); }
    ...
    

    Für das Folgende werden mich wahrscheinlich einige kreuzigen

    [meine höchst subjektive Meinung]
    Da es sich um ein Spiel handelt (i.e. ein abgeschlossenes System mit einemn einzigen Entwickler und nicht allzu groß) sehe ich keine riesen-Gefahr darin x/y von der Player-Klasse als public zu deklarieren und einfach direkt darauf zuzugreifen.

    Damit sparst du dir die ganzen Set/Get methoden in der Player Klasse - und wahrscheinlich auch in der Map-Klasse. Du machst den Zugriff auf die Player-position in der Map-Klasse ja meist nicht einfach so, sondern als Resultat einer Aktion wie schiebePlayer() oder istGeschossImSelbenFeldWiePlayer().

    Set/Get Methoden machen eigentlich nix anderes als private Zeugs öffentlich zu machen. Sie hebeln den eigentlichen Sinn von private Deklarationen aus (Klassen als friend zu deklarieren ist ein weiterer Mechanismus den Sinn von private zu unterlaufen. Was du hier machst ist eigentlich mehr Löcher als im schweizer Käse in den private Block zu schiessen - da kannst du auch gleich alles public machen )

    Private bedeutet: sollte NUR von der Klasse benutzt werden und in unumgänglichen Ausnahmefällen von friend Klassen. Aber meist hast du, wenn du eine Klasse als friend deklarieren musst, irgendwo einen Design-Fehler gemacht.
    [/meine höchst subjektive Meinung]



  • Da stimme ich Antialias zu.
    Statt get/set kann man auch gleich den member public machen.
    Das hier ist immerhin kein Java.
    Allerdings wenn nur die drauf zugreifen dürfen, die es wirklich müssen ist es halt noch etwas sauberer.

    Der Fehler den du hast sagt ja, dass du einen undefinierten Member als Referenz hast.
    Damit ist sicherlich pl gemeint, die ja irgendwas brauch.
    Hast du noch irgendwelche Konstruktoren für Map definiert?
    Beachte, dass du da jeder Referenz einen Wert in der Initialisierungsliste mitgibst.
    Zum Beispiel so:

    Map(Player &pl) : pl(pl) {}
    


  • Wow danke wieder für die Antworten!

    nach mehrmaligem herumprobieren und googeln bin ich darauf gekommen
    dass der Fehler mit

    player& pl;
    

    zusammen hängt.
    Wenn ich das und GetX raus nehme funktioniert auch alles wunderbar (weil ich die Variablen noch nirgends benutze ausse in player).
    Nach antialias Vorschlag habe ich eine kleine Änderung vorgenommen und selbst was geändert:

    class map
    { 
      private:   
      hgeSprite *maps;
      HTEXTURE maptex;
      int tile[8][6];
      //player& pl;
    
      public:
      void update();
      void render(HGE *hge);
      void start(HGE *hge); 
      float GetX(Player &pl) const {return pl.xn();}
    };
    

    Durch das rausnehmen von player& pl; verschwindet erstmal die Fehlermeldung von vorhin jedoch kommt

    16 C:\...\map.h expected ;' before '(' token 17 C:\\...\\map.h expected;' before '}' token



  • Darf ich mal deine komplette Datei bis Zeile 18 sehen?
    Sind die Klammern überall richtig? Hast du das Semikolon nach der Klassendefinition irgendwo vergessen? Beliebter Fehler ist ja:

    class MyClass
    {
      // ...
    } //hier fehlt das Semikolon
    

    Wichtig ist bei solchen Fehlern dass die anderen im Forum auch wissen was bei dir Zeile 16 und 17 ist. Sonst sucht man sich nen Wolf.



  • Ansonsten schau mal ob bei dir das #include "player.h" rausgeflogen ist ...



  • Natürlich natürlich

    #include <hge.h>
    #include <hgeSprite.h>
    
    class map
    { 
      private:   
      hgeSprite *maps;
      HTEXTURE maptex;
      int tile[8][6];
      //player& pl;
    
      public:
      void update();
      void render(HGE *hge);
      void start(HGE *hge);
      float GetX(Player &pl) const {return pl.xn();}
    };
    

    Fehlermeldung:

    16 C:\Users\Veylender\Desktop\hgetests\map.h expected ;' before '(' token 17 C:\\Users\\Veylender\\Desktop\\hgetests\\map.h expected;' before '}' token

    Wenn ich bei Zeile 17 ein Semicolon an erste Stelle packe verschwindet die 2. Fehlermeldung ......
    @padreigh:
    Nein Wenn ich play.h include-iere häufen sich die Fehler nur ....
    Wenn es helfen sollte lade ich mal (ganz dreister weise^^) alles hoch:
    klick mich

    Danke für eure hilfe...
    Lg



  • Das

    player pl;
    

    hast du doch auskommentiert.
    Da kannst du in

    float GetX(Player &pl) const {return pl.xn();}
    

    doch nicht drauf zugreifen wenns das dann gar nicht gibt.

    Und ich hab auch keine Lust jetzt alles runterzuladen und zu entpacken. Erstell du doch bitte mal ne Minimalversion von deinem Code und poste das hier.

    Wird map.h und player.h vielleicht 2 mal includiert? Vielleicht das player.h in deiner map.h und in main.cpp?

    #ifndef _PLAYER_H_
    #define _PLAYER_H_
    
    // hier jetzt deine jetzige player.h
    
    #endif
    

    Vielleicht fehlt das ja.



  • Erstmal danke für deine/eure Geduld mit mir ich weiss ich bin in c++ noch recht schlecht .....

    Ok hier eine gekürzte Fassung mit allem was diesen Fall betrifft:
    main.cpp

    #include <hge.h>
    #include <hgesprite.h>
    #include "play.h"
    #include "map.h"
    
    HGE *hge = 0;
    
    player pl;
    map map1;
    
    bool FrameFunc()
    {     
    
    	if (hge->Input_GetKeyState(HGEK_ESCAPE)) return true;
    	pl.eingabe(hge);
    	map1.update();
    	//... usw.
    

    play.h

    #include <hge.h>
    #include <hgeSprite.h>
    #include <hgeanim.h>
    
    class player
    {
          friend class map;
     private:
     float xa,xn,ya,yn;
     float jfor;
    //.....
    

    map.h

    #include <hge.h>
    #include <hgeSprite.h>
    
    class map
    { 
      private:   
      hgeSprite *maps;
      HTEXTURE maptex;
      int tile[8][6];
      player& pl;
    
      public:
      void update();
      void render(HGE *hge);
      void start(HGE *hge);
      float GetX(player &pl) const {return pl.xn();}
    };
    

    play.cpp und map.cpp haben ausschlieslich Berechnungen mit eigenen Variablen
    Die Fehlermeldung bis jezt sieht so aus:

    4 C:\.....\main.cpp In file included from main.cpp
    C:\.....\map.h In member function float map::GetX(player&) const': 16 C:\\.....\\map.hpl->player::xn' cannot be used as a function
    16 C:\.....\map.h At global scope:
    9 C:\.....\main.cpp structure `map1' with uninitialized reference members
    C:\.....\Makefile.win [Build Error] [main.o] Error 1



  • Du mußt aber in map.h die play.h einbinden, da du ja dort die Klasse "player" benutzt (ansonsten würde auch eine Vorwärtsdeklaration "class player" reichen).
    Und die vielen Fehlermeldungen kommen wahrscheinlich wegen fehlenden "Include-Guards" in den Header-Dateien (s. FAQ http://www.c-plusplus.net/forum/viewtopic-var-t-is-39477.html)



  • Erstmal musst du das player-Objekt in deiner Map initialisieren und zwar im Konstruktor. Eine Referenz darf NIE uninitialisiert sein.
    Das wird eventuell noch durch einen Standardkonstruktor gelößt.

    Das nächste ist, dass die Reihenfolge deiner includes keinen Sinn macht.
    In Map benutzt du schon Player, was durch deine Aussage bekannt ist. In Map setzt du Player als Friend, was zu dem Zeitpunkt noch gar nicht bekannt ist.

    Includiere überall das, was du brauchst und nicht alles nur in der main.
    Jetzt ist aber wichtig dass du dieses #ifndef und #define machst um Mehrfachinkludierung zu vermeiden.


Anmelden zum Antworten