Objekt als Referenz an eine Methode übergeben
-
Hallo,
ich möchte zur Zeit ein kleines Spiel zur Einarbeitung in C++ programmieren.
Ich habe bis jetzt 2 Klassen: Spielfeld, Kugel.
Jetzt will ich die Kugel an den Spielfeld-Konstruktor übergeben:
Feld::Feld(Kugel& kugel, int br, int ho)
Das & bewirkt doch, dass das Objekt nicht kopiert wird, sondern nur eine Referenz auf das Objekt übergeben wird, richtig?
Warum werden dann änderungen an "Kugel", die ich vor dem Erzeugen von Feld mache, nicht "mit übergeben"?
Kugel ball(0,0); ball.moveX(2); Feld feld(ball, 15, 9);
Wie muss ich ein Objekt übergeben, wenn ich will, dass ich in der Methode mit einer Referenz auf das Objekt arbeiten kann?
Ich bin beim Googeln auf das & gestoßen. Leider scheint das nicht zu funktionieren.
MfG Simon
-
lol, weiß nicht!
-
hat mir sehr weitergeholfen.
vllt. will hier jemand noch meinen kompletten code?
#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; } } void main(void) { Kugel ball(0,0); Feld feld(ball, 15, 9); for(int i = 0; i < 10; i++) { ball.moveX(3); ball.moveY(3); feld.show(); Sleep(100); } cout<<endl; system("pause"); }
-
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 Funktionmain()
hat den Rückgabetypint
. Dasvoid
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.