Problem mit einer Methode - C++ Anfänger

leon_20v

Erfahrenes Mitglied
Hallo,

folgender Code:

Code:
class Punkt {
double m_x;    // X-Koordinate
double m_y;    // Y-Koordinate
public:
// Standardkonstruktor
Punkt(double x=1.0, double y=0.0){m_x=x; m_y=y;}
// Erzeuge neuen Punkt als Kopie eines anderen
     Punkt(Punkt &p) {                             }
     ~Punkt();
     // Verschiebeoperator
     ...
};

So die Aufgabe ist einmal, den zweiten Konstruktor Punkt(Punkt &p) zu erstellen, damit da eine Kopie entsteht. Das mit dem "&". Warum muss hier die Adresse von dem Punkt p übergeben werden und kann nicht einfach nur Punkt p stehen?

der komplette Konstruktor sieht ja dann so aus:
Code:
 Punkt(Punkt &p)
 {
      m_x= p.m_x;
      m_y= p.m_y; }


So nun zum Verschiebungsoperator:

vom Proff hab ich folgende Lösung bekommen:
Code:
Punkt& operator +=(double v)
{
m_x += v;
m_y += v;

return *this;
}

also ich kapier das leider überhaubt nicht :(

warum das "&" hier und das +- nach operator, dass kann doch garnicht funktionieren?

Euch wenn es für euch wahrscheine voll die **** frage ist, danke ich euch für eure hilfe.
 
Zum &-Ding:
Normalerweise wird bei einer Funktion eine Variable pass-by-value übergeben:
C++:
void test (int a);
Das heißt, dass der Inhalt der Variable übergeben wird, aber dieser an einer anderen Speicherstelle erstellt wird.
Sprich wenn man in obiger Funktion a verändert, verändert sich nicht die Originalvariable!

Falls man aber die Originalvariable verändern können muss, muss man den Referenzoperator (&) anwenden, so dass die Variable mit pass-by-reference übergeben wird:
C++:
void test (int &a);
Wenn du jetzt a innerhalb der Funktion veränderst, verändert sich auch die ursprüngliche Variable!

Zum +=-Operator:
Du kannst einfach in einer Klasse Operatoren definieren (wie das Beispiel von deinem Lehrer), sodass du diese dann so aufrufen kannst:
C++:
Punkt MeinPunkt;
Punkt += 3;
 
Hi

Zum Konstruktor:
Du übergibst nicht die Adresse (das wäre mit *), sondern eine Referenz.
Kann man sich wie einen zweiten Variablennamen für die selbe Variable vorstellen.
Ohne & werden generell Kopien der Werte übergeben.
Bei einem int etc ist das ja kein Problem, um Punkt zu kopieren wird aber intern wieder dieser Copykonstruktor verwendet.
Folgend würde er sich ohne & selber wieder aufrufen, und immer so weiter...deswegen mit &.

Zum Operator:
C++:
double a;
...
a+=2.00;
Das ist klar, oder?

Und mit deiner operator+= Methode kannst du auch für die Klasse Punkt sowas ermöglichen:
C++:
Punkt p;
...
p+=2.00;

"operator+=" heißt dann eben die Methode, die dabei aufgerufen wird.
Für den double-Parameter wird 2.00 genommen.

Zum return: this liefert für die Klasse die Adresse von ihrer Variable
Beim Punkt p würde ein this innerhalb einer Methode also die Adresse von p liefern.

Und da man bei Pointern mit * auf den Wert zugreift, ist *this quasi das Objekt p selber.

Der Returntyp Punkt& ist wieder eine Referenz, damit durch das return nicht das ganze Objekt kopiert wird.
(was bei einem int-Return tatsächlich passiert, das int wird kopiert. Geht bei größeren Klassen aber in die Zeit, deshalb die Referenz).

Warum man das returnen sollte? Um längere Anweisungen mit mehr als einem Plus etc auch zu ermöglichen.

Gruß
 
Danke für eure Antworten.

Ich steck zwar in der Materie gerade drinn, aber leider verstehe ich eure Antworten nicht :( *heul*

Seid ihr so lieb und könnt das nochmal aufgreifen, was ich davon habe wenn ich das Objekt p mit += erhöhe und das mit dem Punkt& ?

Danke
 
Also:
C++:
int a=12;
int b=123;
b+=a;
Das ist klar, denke ich. b ist jetzt 135
Mit = kannst du den ints Werte zuweisen, und mit += zum einen das andere dazurechnen.
Wie bei ints zugewiesen und addiert wird, muss man selber nicht wissen, das übernimmt der Compiler.

Bei einer Klasse werden die enthaltenen Methoden grundsätzlich mit "variable.methodenname()" aufgerufen.
C++:
class klasse1
{
private:
    int i;
public:
    void zuweisen(int x) { i=x; }
    void plusgleich(int x) { i+=x; }
};
...
klasse1 objekt1;
objekt1.zuweisen(123);
objekt1.plusgleich(12);

Folgendes
C++:
objekt1=123;
objekt1+=12;
wäre jetzt nicht möglich, weil objekt1 ja kein int sondern eine Klasseninstanz ist.
Der Compiler hat keine Ahnung, wie er von dir geschriebene Klassen (eigentlich Objekte) mit ints zusammenaddieren soll.

Um diese += Schreibweise möglich zu machen, gibts jetzt die Möglichkeit, eine Methode "operator+=" in die Klasse zu schreiben
Dasselbe mit =, +, -, *, / ... was man will.
C++:
class klasse1
{
private:
    int i;
public:
    void zuweisen(int x) { i=x; }
    void plusgleich(int x) { i+=x; }
    void operator=(int x) { i=x; }
    void operator+=(int x) { i+=x; }
};
...
klasse1 objekt2;
objekt2=123;
objekt2+=12;

Klarer?
 
okay also ich glaube es hat so bissi geschnackelt...

also mit "operator" kann ich dann sozusagen eine Funktion machen die nur eine Schreibweise ermöglicht. Alternativ könnte ich eben auch diese beiden Funktionen(zuweisen und pusgleich) machen?

jetzt noch eine kleine fragen weil ich dafür noch immer zu blöd bin:
In deinem Bsp. wurde doch jetzt die Variable "x" nicht verändert oder?

da müsste ich doch

Code:
    void zuweisen(int &x) { i=x; }
    void plusgleich(int &x) { i+=x; }

schreiben oder? in deinem Beispiel wird die Variable "i" zu der Variable x und bei "plusgleich" wird x auf i addiert?


Okay das habe ich soweit verstanden, aber was macht das & nach der Klasse "Punkt"?

Code:
Punkt& operator +=(double v)


Ich danke dir sehr für deine Hilfe, damit komm ich wirklich weiter :)
 
Das & bei Punkt& etc sorgt generell dafür, dass keine Kopie der Variablen zurückgegeben/übergeben wird.

Bei einem Aufruf von
C++:
void funktion(int i)
wird eine Kopie vom int übergeben

Bei einem Aufruf von
C++:
void funktion(int *i)
gibt man die Adresse mit; wenn *i in der Funktion verändert wird ändert sich der Wert auch im main.
Genauer gesagt wird die übergebene Adresse kopiert, beide zeigen aber noch immer auf den selben Speicherbereich und somit auf die selbe Variable.

Bei einem Aufruf von
C++:
void funktion(int &i)
wird KEINE Kopie übergeben.
Änderungen in der Variable wirken sich im main etc genauso wie bei den Pointern aus.
Man muss allerdings keinen Stern hinschreiben und muss nicht die Adresse übergeben, sondern übergibt einfach die Variable ganz normal.

Wenn man eine Klasseninstanz ohne & übergibt/zurückgibt, wird das gesamte Objekt jedesmal komplett kopiert.
Je nach dem, wie komplex die Klasse ist kann das vergleichsweise lang dauern und/oder Speicher verbrauchen.
Deswegen sollte man (falls man nicht wirklich eine Kopie will) immer mit Pointern (*) oder Referenzen(&) übergeben.

Bei Grundtypen wie int/float gibts allerdings ein Problem mit int&
Wenn man den Namen einer int-Variable beim übergeben reinschreibt, gibts keine Probleme, bei ints kann man ber auch einfach 123 reinschreiben. Und dann gibts (bei vielen Compilern) Probleme.
Ein einfaches int kopieren ist auch keine Leistungsminderung

Also: int, float etc generell ohne &, für Klassen aber gut geeignet.

also mit "operator" kann ich dann sozusagen eine Funktion machen die nur eine Schreibweise ermöglicht. Alternativ könnte ich eben auch diese beiden Funktionen(zuweisen und pusgleich) machen?

Genau.

void zuweisen(int &x) { i=x; }
void plusgleich(int &x) { i+=x; }

Siehe, oben; besser nur int.
Wenn du statt ints Klasseninstanzen übergeben willst, ist & gut.
Bei ints würde aber nur das Erste von den zwei Codeteilen funktionieren:
C++:
int xyz=123;
...
zuweisen(xyz);
C++:
zuweisen(123);
Manche Compiler kommen auch mit dem Zweiten zurecht, manche aber nicht.

Punkt& operator +=(double v)
Oben hatte ich nur void verwendet, um nicht zu sehr zu verwirren.
Aber du hast recht, bei Operatoren sollte man das generell machen.

Am Schluss schreibt man dazu "return *this;".
Warum? this ist die Adresse des Objekts. Also wenn man bei
C++:
objekt1+=123;
"this" im operator+= verwendet, ergibt das die Adresse von objekt1.

*this (als Pointer gesehen) ist dann objekt1 selber, und eben das Objekt (mit dem man gerade +=123 aufgerufen hat) wird zurückgegeben.
Als Referenz mit & deswegen, um es bei einem += nicht gleich komplett zu kopieren.

Warum man das tun sollte?
Als Beispiel mit operator=:
C++:
Punkt a;
Punkt b;
Punkt c;
...
a=b=c;

Wenn der operator= als Rückgabetyp void hätte, müsste man
C++:
b=c;
a=b;
schreiben.

So wird zuerst "b=c" gemacht, das gibt b zurück und übrig bleibt "a=b)".

Man gibt also eine Referenz auf das Objekt zurück, um komplexere Ausdrücke zu ermöglichen.
Wenn man zeilenlange Formeln mit zehn Variablen hat, freut man sich, dass man nicht jede einzelne Anweisung extra schreiben muss.

Gruß
 
Zuletzt bearbeitet:
Zurück