assignment operator überschreiben damit er Referenzen gleich setzt
-
Hallo,
Ich habe eine Klasse NamespaceTest und will den = operator so überschreiben, dass er einfach eine zweite Referenz auf das selbe Objekt erzeugt. Aber so klappt es nicht. Kann mir jemand sagen wie?
#ifndef GUARD_namespacetest_h #define GUARD_namespacetest_h #include <iostream> class NamespaceTest { public: NamespaceTest():member{1}, member2{1.0} {}; NamespaceTest(int, double); NamespaceTest(const NamespaceTest& ref){ this->member = ref.member; this->member2 = ref.member2; } NamespaceTest& operator=(NamespaceTest& ref){ // das funktioniert nicht. *this = ref; return ref; } ~NamespaceTest(){std::cout << "destructor of NamespaceTest called.";}; int get_member(); void set_member(int x); double get_member2() const; private: int member; double member2; }; #endif
#include <iostream> #include <vector> #include "NamespaceTest.h" #include <string> #include "Str.h" int main(){ NamespaceTest q{}; NamespaceTest j = q; q.set_member(10); // Ausgabe: 1 = member2 of j. std::cout << j.get_member() << " = member2 of j." << std::endl; return 0; }
-
Was heißt "Aber so klappt es nicht" bzw. "das funktioniert nicht"?
Bitte poste zukünftig Fehlermeldungen des Compilers oder beschreibe das Laufzeitverhalten, damit machst du es anderen leichter, dir zu helfen.In Zeile 18 wird rekursiv
operator=
aufgerufen, das sollte in einem stack overflow enden.
Den Assignment Operator kann man gut mit dem Copy-and-swap Idiom umsetzen, das bietet gleichzeitig eine strong-exception-guarantee:// Auszug: void NamespaceTest::swap( NamespaceTest& other ) noexcept { // ggf. passende swap-Funktion auswählen std::swap( member, other.member ); std::swap( member2, other.member2 ); } NamespaceTest& operator=( NamespaceTest ref ) // <= Call by value! { swap( *this, ref ); return *this; }
Durch call-by-value wird eine Kopie des neuen Wertes erzeugt, die verändert werden darf. Damit ist ein noexcept-swap möglich und erfüllt die strong-exception-guarantee.
-
@DocShoe ich habe die main methode beigefügt und reingeschrieben was die ausgabe ist, es ist keine endlos rekursion.
-
In Zeile 10) der main.cpp wird auch nicht der Zuweisungsoperator aufgerufen, sondern der Kopierkonstruktor.
Daher:
Bitte poste zukünftig Fehlermeldungen des Compilers oder beschreibe das Laufzeitverhalten, damit machst du es anderen leichter, dir zu helfen.
-
DocShoe hat recht.
So könnte es besser klappen:
#ifndef GUARD_namespacetest_h #define GUARD_namespacetest_h #include <iostream> class NamespaceTest { public: NamespaceTest() : member{1}, member2{1.0} {} NamespaceTest(int m, double m2) : member{m}, member2{m2} {} // Kopierkonstruktor mit Initialisierungsliste NamespaceTest(const NamespaceTest& ref) : member{ref.member}, member2{ref.member2} {} // Korrigierter Kopierzuweisungsoperator NamespaceTest& operator=(const NamespaceTest& ref) { if (this != &ref) { // Selbstzuweisung vermeiden member = ref.member; member2 = ref.member2; } return *this; } ~NamespaceTest() = default; // Keine unnötigen Ausgaben im Destruktor int get_member() const; void set_member(int x); double get_member2() const; private: int member; double member2; }; #endif
und
#include "NamespaceTest.h" // Getter-Methoden int NamespaceTest::get_member() const { return member; } void NamespaceTest::set_member(int x) { member = x; } double NamespaceTest::get_member2() const { return member2; }
und in der Anwendung:
#include <iostream> #include "NamespaceTest.h" int main() { NamespaceTest q{}; NamespaceTest j = q; // Kopierkonstruktor q.set_member(10); // Ausgabe: 1 = member of j (da q kopiert wurde und j unabhängig ist) std::cout << j.get_member() << " = member of j." << std::endl; return 0; }
-
@Erhard-Henkes
Aber damit hast du keine strong exception guarantee mehr. Wenn Zeile 18 ne exception wirft istthis
in einem inkonsistenten Zustand.