Sagen wir, ich möchte operator =
überschreiben, damit ich etwas wie
Dann habe ich in meiner Implementierung von operator =
etwas in der Art:
Machen Sie sich nichts vor der Implementierung, es funktioniert bereits.
Mein Problem ist, dass was passiert, wenn Sie return *this
? Ich weiß, dass es einen Verweis auf das Objekt gibt, aber ist das was passiert?
Sie return *this
, damit Sie normale zusammengesetzte C ++ =
-Anweisungen schreiben können wie:
weil diese Aussage grundsätzlich lautet:
%Vor% Wenn p2.operator=(...)
nicht return *this
hätte, hättest du nichts Sinnvolles an p3.operator=(...)
weitergeben können.
p2 = p1
ist eine Abkürzung für p2.operator=(p1)
. Es ruft nur Ihre Funktion operator=
auf, die einen Verweis auf p2
zurückgibt, den Sie dann ignorieren. Um dies deutlich zu machen, nennen wir es assign
anstelle von operator=
:
Jetzt würden Sie anstelle von p2 = p1
schreiben
In diesem Fall wird das Ergebnis von assign
ignoriert, aber Sie müssen es nicht ignorieren. Zum Beispiel könnten Sie schreiben:
Mit operator=
anstelle von assign
wird
Da die Zuweisung jedoch rechtsassoziativ ist, kann dies auch als
geschrieben werden %Vor% Diese Form, mehrere Aufgaben gleichzeitig ausführen zu können, stammt ursprünglich von C und wurde in C ++ durch die Konvention von *this
in operator=()
beibehalten.
Man könnte versucht sein, den Kopierzuweisungsoperator dazu zu bringen, void
zurückzugeben, wenn Sie sowieso keine verketteten Zuweisungen benötigen (wie in den anderen Antworten gezeigt). Schließlich sind verkettete Aufgaben oft schwer zu lesen und zu verstehen, so dass sie nicht als eine Verbesserung betrachtet werden können.
Ein oft übersehener Aspekt ist jedoch, dass void operator=(Poly& const)
bedeutet, dass Ihr Typ die nicht mehr erfüllt CopyAssignable
concept , das einen T&
Rückgabetyp erfordert.
Ein Typ, der das CopyAssignable
-Konzept nicht erfüllt, kann nicht offiziell für einige Standard-Container-Operationen verwendet werden, zum Beispiel std::vector::insert
, was bedeutet, dass das folgende scheinbar unschuldige Stück Code undefiniertes Verhalten ergibt, obwohl es wahrscheinlich läuft völlig in Ordnung:
Wie der C ++ - Standard in § 17.6.4.8/2.3 erläutert, spricht er von Einschränkungen bei Programmen, die die Standardbibliothek verwenden:
(...) In den folgenden Fällen sind die Effekte undefined :
(...) für Typen, die bei der Instantiierung von a als Vorlagenargumente verwendet werden Template-Komponente, wenn die Operationen auf dem Typ nicht das implementieren Semantik der zutreffenden Anforderungen (...).
Natürlich ist es genau weil des undefinierten Verhaltens, dass ein Compiler den Fehler ignorieren darf und das Programm sich so verhält, dass er dem offensichtlich beabsichtigten Verhalten entspricht. Aber das ist nicht nötig.
Sie sollten auch berücksichtigen, dass Sie nicht alle zukünftigen Verwendungen Ihres Poly
-Typs vorhersagen können. Jemand könnte eine Template-Funktion schreiben wie:
Diese Funktion würde dann nicht mit Ihrer Poly
-Klasse funktionieren.
Verstoßen Sie einfach nicht gegen diese C ++ - Konvention und Sie werden keine Probleme bekommen.
Was passiert, wenn Sie * das zurückgeben?
In Ihrem Beispiel ( p2 = p1;
) nichts. Die Methode kopiert p1
in p2
und gibt einen Verweis auf das Objekt 'this' zurück, das der aufrufende Code nicht verwendet.
In Code wie p3 = p2 = p1;
ist der erste Aufruf p2 = p1
, der p1
in p2
kopiert und einen Verweis auf p2
zurückgibt. Der aufrufende Code kopiert dann von dieser Referenz zu p2
in p3
(und ignoriert den Verweis auf p3
, der zurückgegeben wird).
(Nebenbei: Stellen Ihre Unit-Tests sicher, dass p1 = p1
ordnungsgemäß funktioniert? Diesen Fall können Sie leicht vergessen!)
Das Zurückgeben eines Verweises auf das Zielobjekt erlaubt das Zuweisen von Verkettungen (Kaskaden) und das Überladen von Operatoren innerhalb einer Klasse folgt rechtsassoziativ (klicken Sie auf hier für detaillierte Regeln zum Überladen von Operatoren)
%Vor%Tags und Links c++ assignment-operator copy-assignment