Hallo,
ich habe hier eine überladene Operatorfunktion und die scheint irgendwo einen Konstruktor zu verwenden, ich verstehe nur nicht wo oder warum. Kann mir das jemand erklären?
Meine main führt folgendes aus:
Die überladene Operatorfunktion:Code:Bruch b1(1,2); Bruch b2(2,3); Bruch b3 = b1 * b2;
Der Konstruktor:Code:const Bruch & Bruch::operator *= (const Bruch &b) { [INDENT]return *this = *this * b;[/INDENT] }
Der Kopier-Konstruktor:Code:Bruch::Bruch(int z, int n) : zaehler(z), nenner(n) { [INDENT]cout << "Konstruktor" << endl;[/INDENT] }
Meiner erwartete Ausgabe wäre:Code:Bruch::Bruch(const Bruch &rhs) { [INDENT]cout << "Kopier-Konstruktor" << endl; zaehler = rhs.zaehler; nenner = rhs.nenner;[/INDENT] }
Konstruktor...
Konstruktor...
Konstruktor...
Die Ausgabe ist diese:
Konstruktor...
Konstruktor...
Konstruktor...
Konstruktor...
Also ein Konstruktoraufruf mehr als gedacht. Wo liegt mein Denkfehler? Oder wo meine Unwissenheit?
-
13.09.2011, 20:18 #1Lt. Junior Grade
- Dabei seit
- Jan 2011
- Ort
- Bruchsal
- Beiträge
- 400
[C++] Konstruktor-Aufruf-Suche im Code
Geändert von derBobby (13.09.2011 um 21:08 Uhr)
- Anzeige
Logge dich ein, um diese Anzeige nicht zu sehen. -
13.09.2011, 20:24 #2Fleet Admiral
- Dabei seit
- Mai 2010
- Beiträge
- 13.184
[C++] AW: Konstruktor-Aufruf-Suche im Code
1. Bruch b1(1,2);
2. Bruch b2(2,3);
3. + 4. Bruch b3 = b1 * b2;
Der dritte ist Bruch b3
der vierte ist das Ergebnis b1 * b2 und der wird dann b3 zugewiesen.
Baue ggf. einen Kopierkonstruktor Bruch::Bruch(Bruch b) {...}
und mache
Bruch b3 (b1 * b2);
dann hast Du nur 3 Aufrufe zwei Deines Konstruktors und einen des Kopierkonstruktors.Macht eure Augen auf um zu sehen, sonst braucht ihr sie um zu weinen.
Medienkompetenz heißt auch: Nachrichten nach ihrer Vertrauenswürdigkeit selbst zu bewerten, denn im Internet kann jeder Idiot schreiben und man muß alle Informationen selbst bewerten! In den Massenmedien dürfen nur reiche Idioten schreiben! Wer ein kritischer Mensch ist, der wird auch die Medien kritisch nutzen, bei den anderen ist Hopfen und Malz verloren. Also: Nichts glauben, selbst prüfen und selbst denken!
-
13.09.2011, 20:26 #3
[C++] AW: Konstruktor-Aufruf-Suche im Code
Fehlt da nicht noch der Code für die reine Multiplikation in deinem Post?
EDIT: naja, Problem scheint ja schon gelöst...Geändert von sash2k2 (13.09.2011 um 20:29 Uhr)
-
13.09.2011, 20:31 #4
[C++] AW: Konstruktor-Aufruf-Suche im Code
Zeig uns mal den kompletten Code. Also inklusive operator * und Kopierkonstruktor. Dein operator *= ist außerdem etwas seltsam implementiert. Normalerweise nutzt man in der Implementierung von operator * den operator *= und nicht umgekehrt. Also:
Ergänzung vom 13.09.2011 20:36 Uhr: An dieser Stelle möchte ich mal anmerken, daßCode:class Bruch { public: Bruch(int z, int n) : zaehler(z), nenner(n) { cout << "Konstruktor" << endl; } Bruch( const Bruch& rhs ) : zaehler( rhs.zaehler ), nenner( rhs.nenner ) { cout << "Kopierkonstruktor" << endl; } Bruch& operator *= ( const Bruch& rhs ) { zaehler *= rhs.zaehler; nenner *= rhs.nenner; return *this; } Bruch operator * ( const Bruch& rhs ) const { Bruch result( *this ); result *= rhs; return result; // könnte man noch kürzen schreiben: //return Bruch( *this ) *= b; } private: int zaehler; int nenner; };
Bruch b3 (b1 * b2);
lediglich ein andere Schreibweise für
Bruch b3 = b1 * b2;
ist. In beiden Fällen wird b3 über den Kopierkonstruktor erstellt.Geändert von antred (13.09.2011 um 22:28 Uhr)
-
13.09.2011, 20:38 #5Lt. Junior Grade
Ersteller dieses Themas
- Dabei seit
- Jan 2011
- Ort
- Bruchsal
- Beiträge
- 400
[C++] AW: Konstruktor-Aufruf-Suche im Code
Was heißt reine Multiplikation? Bruch * Int?
Kopierkonstruktor brauche ich ja atm nicht zum Verstehen, denke ich. operator* habe ich nicht, die Multiplikation funktioniert auch ohne.
Ich denke mir fehlt einfach das Verständniss für die Zeile:
this* = *this * b;
In dieser müsste ja dann der vierte Aufruf stattfinden, oder etwa im Funktionskopf?
EDIT:
Oh Mann, natürlich! Kopierkonstruktor. Das liegt in keiner Weise am *this. Tja, das ist das tolle am Quellcode, da passieren Dinge, die da gar nicht explizit stehen
Zitat von antred
Danke euch allen!
EDIT2:
Heißt das dann, dass es immer der Kopierkonstruktor ist, wenn da steht:
Bruch b5 = *whatever* ?Geändert von derBobby (13.09.2011 um 20:42 Uhr)
-
13.09.2011, 20:43 #6
[C++] AW: Konstruktor-Aufruf-Suche im Code
Und jetzt noch was. Wenn du mit Optimierungen übersetzt, kann es sogar passieren, daß am Ende weniger Kopierkonstruktoraufrufe rauskommen, als man erwarten würde, denn es ist dem Compiler freigestellt, sogenannte "temporaries" wegzuoptimieren, SELBST WENN DER KOPIERKONSTRUKTOR NEBENEFFEKTE HAT (und somit der Programmablauf durch das Wegoptimieren der Kopierkonstruktoren verändert würde)!
http://en.wikipedia.org/wiki/Copy_elision
-
13.09.2011, 20:46 #7Lt. Junior Grade
Ersteller dieses Themas
- Dabei seit
- Jan 2011
- Ort
- Bruchsal
- Beiträge
- 400
[C++] AW: Konstruktor-Aufruf-Suche im Code
Dann kann man sich damit quasi auch noch das Programm zerschiessen? Sind ja super Möglichkeiten!

EDIT: Bitte frage am Ende meines letzten Posts nicht überlesen!
-
13.09.2011, 20:54 #8
[C++] AW: Konstruktor-Aufruf-Suche im Code
Wenn *whatever* ein Bruch ist oder ein Ausdruck, der als Ergebnis eine Bruch-Instanz liefert, dann ja. Wenn auf der rechten Seite ein Ausdruck steht, der keine Bruch-Instanz liefert, dann wird der Compiler versuchen, einen Kandidaten zu finden, mit dem das Ding auf der rechten Seite in einen Bruch-Instanz konvertiert werden kann (nicht als explicit deklarierte Bruch-Konstruktoren mit einem Argument oder einen geeigneten cast-Operator).
Ergänzung vom 13.09.2011 20:56 Uhr: Nur wenn deine Kopierkonstruktoren noch Nebeneffekte haben (also mehr machen, als nur eine Kopie zu erstellen) und du dich absolut auf diese Nebeneffekte verläßt. Das wäre dann aber ohnehin bad practice.
-
13.09.2011, 20:59 #9Lt. Junior Grade
Ersteller dieses Themas
- Dabei seit
- Jan 2011
- Ort
- Bruchsal
- Beiträge
- 400
[C++] AW: Konstruktor-Aufruf-Suche im Code
*this = *this * b;
Was davon ruft dann aber den Konstruktor auf, bzw. muss umgewandelt werden? Hinter dem *this steht der erste Bruch vor dem Operator *= und b ist ja auch schon ein Bruch. Also dürfte es doch keinen Aufruf geben?
EDIT: Kopierkonstruktor der Vollständigkeit halber eingebaut. Code siehe oben.Geändert von derBobby (13.09.2011 um 21:07 Uhr)
-
13.09.2011, 21:11 #10
[C++] AW: Konstruktor-Aufruf-Suche im Code
Moment, ich sprach von
Bruch b3 = b1 * b2;
! Folgendes:
Bruch b3;
b3 = b1 * b2;
Wäre schon wieder ein völlig andere Geschichte.
Hier würde b3 erst mal über einen parameterlosen Defaultkonstruktor erstellt (es sei denn, deine Klasse hat keinen ... dann würde sich die Zeile Bruch b3; überhaupt nicht kompilieren lassen). Anschließend würde dann das Ergebnis von b1 * b2 berechnet. Diese Berechnung gibt eine "temporary" zurück, die mit dem Kopierkonstruktor erstellt wird. Diese temporary wird dann mit dem Zuweisungsoperator (operator =) an b3 zugewiesen.
Ergänzung vom 13.09.2011 21:13 Uhr: Ich würde dir raten, zaehler und nenner nicht im Rumpf des Kopierkonstruktors sondern, wie du es bei dem anderen Konstruktor auch getan hast, mit einer Initialisierungsliste zu initialisieren.
-
13.09.2011, 21:17 #11Lt. Junior Grade
Ersteller dieses Themas
- Dabei seit
- Jan 2011
- Ort
- Bruchsal
- Beiträge
- 400
[C++] AW: Konstruktor-Aufruf-Suche im Code
Also schön, neuer Gedanke um meine Frage richtig zu formulieren.
Die Frage ist jetzt halt, was genau in der Funktion löst den Konstruktor aus, weil *this im Prinzip ein Bruch ist, genauso wie b?:Code:Bruch b1(1,1); Bruch b2(1,1); b1 = b2 * b2; <- diese Zeile ruft einmal Konstruktor und einmal Destruktor auf.
Code:const Bruch & Bruch::operator *= (const Bruch &b){ [INDENT]return *this = *this * b;[/INDENT] }Geändert von derBobby (13.09.2011 um 21:20 Uhr)
-
13.09.2011, 21:43 #12
[C++] AW: Konstruktor-Aufruf-Suche im Code
Zitat von derBobby
Kann nicht sein. Irgend wo in deinem Programm muß ein operator * für 2 Operanden vom Typ Bruch definiert sein, sonst würde sich dein Code nicht kompilieren lassen. Und eben diesen operator * solltest du jetzt mal rausrücken, denn von der Implementierung hängt ab, was bei
Bruch a( 1, 2 );
Bruch b( 3, 4 );
Bruch c = a * b;
eigentlich so abläuft. Notfalls schmeiß halt mal deinen Debugger an und steppe durch a * b; nur um zu sehen, wo dieser operator eigentlich definiert ist.
-
13.09.2011, 21:56 #13Lt. Junior Grade
Ersteller dieses Themas
- Dabei seit
- Jan 2011
- Ort
- Bruchsal
- Beiträge
- 400
[C++] AW: Konstruktor-Aufruf-Suche im Code
Ich könnt mich schlagen! Wie blind kann ein Einzelner sein?
*AufKnienRumRutschUndUmVerzeihungBitt*Code:inline Bruch Bruch::operator * (const Bruch &b) const { return Bruch(zaehler * b.zaehler, nenner * b.nenner); }
Und auf einmal ist es sogar mir klar. Bevor ich hier gepostet hab, bin ich den Code zwei Mal durch und habe nach der Operator-Funktion gesucht. Zwei Mal überlesen...
Kann man die Fkt auch so gestalten, dass kein weiterer Konstruktor notwendig ist?
-
13.09.2011, 22:20 #14
[C++] AW: Konstruktor-Aufruf-Suche im Code
Nee.
Ich würde den operator * zwar so schreiben, daß er unter der Haube letztendlich die Implementierung vom operator *= nutzt ... aber ist Geschmackssache. Aber um den Konstruktor für die temporary kommst du nicht umhin. Aber keine Sorge, moderne Compiler sind beim Optimieren ziemlich aggressiv, und so manche temporary wird in einem optimierten Build einfach wegfallen.
-
16.09.2011, 07:37 #15Fleet Admiral
- Dabei seit
- Mai 2010
- Beiträge
- 13.184
[C++] AW: Konstruktor-Aufruf-Suche im Code
Doch, Du kannst einen Konstruktor schreiben, der zwei Brüche aufnimmt und diese multipliziert:
Bruch( const Bruch& mb1, const Bruch& mb2 )
{
zaehler = mb1.zaehler * mb2.zaehler;
nenner = mb1.nenner * mb2.nenner;
}
Wenn Du das aber auch für z.B. die Division machen willst, dann hast Du ein Problem.Macht eure Augen auf um zu sehen, sonst braucht ihr sie um zu weinen.
Medienkompetenz heißt auch: Nachrichten nach ihrer Vertrauenswürdigkeit selbst zu bewerten, denn im Internet kann jeder Idiot schreiben und man muß alle Informationen selbst bewerten! In den Massenmedien dürfen nur reiche Idioten schreiben! Wer ein kritischer Mensch ist, der wird auch die Medien kritisch nutzen, bei den anderen ist Hopfen und Malz verloren. Also: Nichts glauben, selbst prüfen und selbst denken!
-
16.09.2011, 10:06 #16
[C++] AW: Konstruktor-Aufruf-Suche im Code
Das ändert nicht das geringste an der Zahl der Konstruktordurchläufe, die für den operator * stattfinden. Wenn du das anders siehst, erklär's mir bitte.
-
17.09.2011, 19:17 #17Fleet Admiral
- Dabei seit
- Mai 2010
- Beiträge
- 13.184
[C++] AW: Konstruktor-Aufruf-Suche im Code
antred, wo wird denn bei der Lösung mit dem "Bruch( const Bruch& mb1, const Bruch& mb2 )" Konstruktor noch ein weiterer Konstruktor aufgerufen?
Macht eure Augen auf um zu sehen, sonst braucht ihr sie um zu weinen.
Medienkompetenz heißt auch: Nachrichten nach ihrer Vertrauenswürdigkeit selbst zu bewerten, denn im Internet kann jeder Idiot schreiben und man muß alle Informationen selbst bewerten! In den Massenmedien dürfen nur reiche Idioten schreiben! Wer ein kritischer Mensch ist, der wird auch die Medien kritisch nutzen, bei den anderen ist Hopfen und Malz verloren. Also: Nichts glauben, selbst prüfen und selbst denken!
-
18.09.2011, 12:39 #18
[C++] AW: Konstruktor-Aufruf-Suche im Code
Um etwaige Mißverständnisse auszuschließen, es geht darum, derBobby's Implementierung für den "operator *", welche zur Zeit so aussieht:
so zu gestalten, daß der Kopier-Konstruktor für die von der Methode zurückgegebenen temporary entfällt. Das ist schlicht und ergreifend nicht möglich. Die von dir vorgeschlagene Implementierung für den "operator *":Code:inline Bruch Bruch::operator * (const Bruch &b) const { return Bruch(zaehler * b.zaehler, nenner * b.nenner); }
erzeugt diesen temporary genauso wie jede andere mögliche (korrekte) Implementierung von "operator *".Code:Bruch( const Bruch& mb1, const Bruch& mb2 ) { zaehler = mb1.zaehler * mb2.zaehler; nenner = mb1.nenner * mb2.nenner; } inline Bruch Bruch::operator * (const Bruch &b) const { return Bruch( *this, b ); }Geändert von antred (18.09.2011 um 12:46 Uhr)
-
20.09.2011, 06:55 #19Fleet Admiral
- Dabei seit
- Mai 2010
- Beiträge
- 13.184
[C++] AW: Konstruktor-Aufruf-Suche im Code
Wo wird denn bitte bei dem Konstruktor ein Temporary erzeugt:
Bruch( const Bruch& mb1, const Bruch& mb2 )
{
zaehler = mb1.zaehler * mb2.zaehler;
nenner = mb1.nenner * mb2.nenner;
}
Den * operator nutze ich nicht, denn mit dem kommt man um einen temporary nicht herum, den es aber zu verhindern ging, so wie ich das verstanden habe.
Aber egal, ich klinge mich jetzt hier aus.Macht eure Augen auf um zu sehen, sonst braucht ihr sie um zu weinen.
Medienkompetenz heißt auch: Nachrichten nach ihrer Vertrauenswürdigkeit selbst zu bewerten, denn im Internet kann jeder Idiot schreiben und man muß alle Informationen selbst bewerten! In den Massenmedien dürfen nur reiche Idioten schreiben! Wer ein kritischer Mensch ist, der wird auch die Medien kritisch nutzen, bei den anderen ist Hopfen und Malz verloren. Also: Nichts glauben, selbst prüfen und selbst denken!
-
20.09.2011, 10:39 #20
[C++] AW: Konstruktor-Aufruf-Suche im Code
Holt, DerBobby's Frage lautete doch ganz klar:
Und da er nur ein paar Zeilen über dieser Frage seine Implementierung vom operator * postete, ist es doch nicht unvernünftig, anzunehmen daß er mit "die Fkt" den operator * meinte, oder?Kann man die Fkt auch so gestalten, dass kein weiterer Konstruktor notwendig ist?

Zitieren
