Objekt als Referenz an eine Methode übergeben



  • Du übergibst zwar eine Referenz an Deinen Konstruktor, aber im Konstruktor machst Du eine Zuweisung an ein Objekt:

    ball = Kugel;

    Dabei wird das Objekt kopiert. Du hast fortan zwei (verschiedene) Objekte, einmal den ball in Feld und kugel in main.
    Mögliche Lösung:

    Speichere in feld einen Zeiger auf ein Objekt vom Typ Kugel und übergib einen Zeiger an den Konstruktor, anstelle einer Referenz.



  • Hallo! schrieb:

    ...
    Warum werden dann änderungen an "Kugel", die ich vor dem Erzeugen von Feld mache, nicht "mit übergeben"?...

    Dein Fehler liegt woanders: Du legst in Feld eine Kopie von Kugel an. Deren Zustand ändert sich natürlich nicht, wenn Du "das äußere Kugel" änderst.
    Wenn Du die beiden Objekte (also das ball und feld.ball) dauerhaft gekoppelt haben möchtest (sprich: Es gibt nur ein Objekt), dann solltest Du das auch so verdrahten:

    class Feld
    {
      private:
       Kugel& ball; // Hier also kein eigenes Objekt, sondern nur eine Referenz.
       int breite;
       int hoehe;
    ...
    
    Feld::Feld(Kugel& kugel, int br, int ho) 
    : ball(kugel), breite(br), hoehe(ho) {} // "Initialisierungsliste"
    

    Gruß,

    Simon2.



  • Belli schrieb:

    Speichere in feld einen Zeiger auf ein Objekt vom Typ Kugel und übergib einen Zeiger an den Konstruktor, anstelle einer Referenz.

    Was spricht denn gegen eine Referenz? Genau in diesem Falle wäre es doch praktisch, weil Feld während der ganzen Lebensdauer auf ein externes Objekt verweist. Man muss Referenzen einfach in der Konstruktor-Initialisierungsliste initialisieren, aber daran sollte man sich sowieso gewöhnen.

    Übrigens: void main() ist kein Standard-C++! Die Funktion main() hat den Rückgabetyp int . Das void in Klammern ist in C++ auch eher unüblich, aber erlaubt.
    (Der Header <conio> und die Windows-Funktionen sind im Weiteren auch nicht standardkonform.)



  • Belli schrieb:

    ...Speichere in feld einen Zeiger auf ein Objekt vom Typ Kugel und übergib einen Zeiger an den Konstruktor, anstelle einer Referenz.

    Warum mit Zeigern ? Referenzen tuns doch auch und sind in vielerlei Hinsicht praktischer.
    Allerdings geht das halt nicht, wenn man "umhängen" muss.

    Gruß,

    Simon2.



  • Nexus schrieb:

    Belli schrieb:

    Speichere in feld einen Zeiger auf ein Objekt vom Typ Kugel und übergib einen Zeiger an den Konstruktor, anstelle einer Referenz.

    Was spricht denn gegen eine Referenz? Genau in diesem Falle wäre es doch praktisch, weil Feld während der ganzen Lebensdauer auf ein externes Objekt verweist.

    Nix spricht dagegen.



  • Danke für die Antworten!
    Ich habe es mit der Referenz gelöst.

    C++ ist halt schon ne ziemliche Umstellung, wenn man davor nur PHP gemacht hat.

    So sieht mein jetziger Code aus:

    #include<iostream>
    #include<conio>
    using namespace std;
    
    class Kugel
    {
        private:
         int x;
         int y;
    
        public:
          Kugel(int posX, int posY);
          int getX();
          int getY();
          void moveX(int val);
          void moveY(int val);
    };
    
    Kugel::Kugel(int posX = 0, int posY = 0)
    {
       x = posX;
       y = posY;
    }
    
    int Kugel::getX()
    {
      return x;
    }
    
    int Kugel::getY()
    {
      return y;
    }
    
    void Kugel::moveX(int val)
    {
     x = x + val;
    }
    
    void Kugel::moveY(int val)
    {
     y = y + val;
    }
    
    class Feld
    {
      private:
       Kugel& ball;
       int breite;
       int hoehe;
    
      public:
        Feld(Kugel& kugel, int br, int ho);
        void show();
    };
    
    Feld::Feld(Kugel& kugel, int br, int ho)
          : ball(kugel), breite(br), hoehe(ho)
    {}
    
    void Feld::show()
    {
       clrscr();
       for(int i = 0; i < hoehe; i++)
       {
         for(int j = 0; j < breite; j++)
         {
           if(ball.getX() == j && ball.getY() == i)
           {
             cout<<".";
           }
           else
           {
              cout<<"_";
           }
         }
         cout<<endl;
       }
    }
    
    int main()
    {
      Kugel ball(0,0);
      Feld feld(ball, 15, 9);
    
      int Taste = 0;
      feld.show();
      while(1) // Wenn noch keine Taste gedrückt wurde
      {
    
        if(kbhit())
        {
        Taste = getch();
        if(Taste == 0) // Spezielle Taste wie Pfeile usw.
         {
            Taste = getch(); // Spezielle Taste einlesen
    
            switch(Taste)
            {
             case 77: ball.moveX(1); break;
             case 75: ball.moveX(-1); break;
             case 72: ball.moveY(-1); break;
             case 80: ball.moveY(1); break;
            }
            feld.show();
         }
         }
    }
    
      cout<<endl;
      getch();
    
      return 0;
    }
    

    Man kann jetzt die Kugel bewegen. Es sind noch keine Begrenzungen eingebaut. Man kann also aich aus dem Feld hinausfliegen.

    Aber immerhin weiß ich jetzt, wie ich Objekte übergeben kann 🙂

    Gibt es sonst noch etwas an meinem Code, was nicht so ganz richtig ist?
    Wie ich conio ersetzen kann, weiß ich nicht. Den Rest habe ich umgesetzt.



  • - const corectness (getter verändern das Obejekt ja nicht)
    - initialisierungsliste (einmal machst du sie einmal nicht?!)
    - ev. inline
    - Geschmackssache:

    cout<<".";
    

    Finde ich hässlich zu lesen. Ich bevorzuge da Abstände dazwischen.

    cout << ".";
    

    Der Rest sollte mit der Zeit von alleine kommen.



  • Eine Endlosschleife mach man eigentlich mit

    for(;;)
    

    Manche Compiler meckern sogar bei while(1).



  • Borland C++ scheint das nicht zu stören. So habe ich es bis jtezt auch in allen anderen Sprachen gelöst



  • btw:

    es gibt auch einen operator +=
    (z.bsp. bei move)

    außerdem solltest du move vll eher so deklarieren:

    void Move (int dX, int dY = 0);
    

    und so definieren:

    void Kugel::Move (/*const - ist geschmackssache*/ int dX, /*const - ...*/ dY)
    {
       x += dX;
       y += dY;
    }
    

    bb



  • Was bringt das "const" im Funktionskopf? Versteh ich nicht so ganz



  • Hallo! schrieb:

    Was bringt das "const" im Funktionskopf? Versteh ich nicht so ganz

    Das besagt, dass diese (Member-)Funktion das zugehörige Objekt nicht ändert.
    Beispiel:

    struct A {
       int i;
       void f() const; // diese Funktion ändert i ("Zustand eines A-Objekts") nicht
       void g(); // diese Funktion vielleicht auch nicht ... könnte es aber auch
    };
    

    Das ist ein Werkzeug, um das Konzept der "const-correctness" anzuwenden.
    Man kann const noch an anderen Stellen anwenden:

    void f(int const& i); // diese Funktion nimmt zwar eine Referenz auf ein int entgegen,
       // wird aber das übergebene i nicht ändern
    
    int main() {
       int const i = 2; // i wird keinen anderen Wert annehmen
       int a = 3;
       f(a); 
       // ... hier weiß ich, dass a immer noch den Wert 3 hat
       i = 7; // => Compilerfehler: i sollte ja nicht mehr geändert werden.
    

    Dieses Konzept macht nicht direkt das Programm "schneller" oder "kürzer" oder ... aber eben strukturierter, was deutlich Sicherheit und Verständlichkeit bringt.
    Theoretisch kann man ein Programm auch komplett ohne const schreiben ... aber da nimmt man sich Möglichkeiten, auf die ich nicht verzichten wollte.

    Gruß,

    Simon2.


Anmelden zum Antworten