Kleine Operator Fragen
-
Hallo,
ich habe mir gerade den Operator Artikel aus dem Magazin ( http://magazin.c-plusplus.net/artikel/�berladung von Operatoren in CPlusPlus (Teil 1) ) durchgelesen und habe (wie zu erwarten) nun ein paar kleine Fragen:
1. Der Autor rät, unäre Operatoren immer als Klassenmethode zu definieren: "Wenn unäre Operatoren nicht als Klassenmethode überladen werden, ist eine implizite Konvertierung des Arguments möglich, was meist ein unerwartetes Feature ist." Das leuchtet mir nicht ein. Wenn ich jetzt eine Klasse rational schreibe und sowas haben will: r1 = -r2; dann würde ich operator- eher als freie Funktion definieren, weil das Objekt selber ja NICHT verändert wird, sondern nur ein verändertes Objekt zurückgegeben wird (wie beim binären +,-,* etc). Kann mir sagen (oder ein Beispiel geben), wieso die unären Operatoren in die Klasse sollten?
2. Sein operator= sieht so aus:
X& X::operator= (X const& rhs);Und er schreibt dazu: "Da kein neues Objekt erzeugt wird, reicht eine Referenz als Rückgabewert, dies ermöglicht Kettenzuweisungen á la a = b = c."
Eine Kettenzuweisung würde doch auch gehen, wenn ich KEINE Referenz zurückgebe, sondern nur ein normales Objekt, alsoX X::operator= (X const& rhs);, oder? Den einzigen Unterschied (neben Effizienz) der Referenz sehe ich hier: (a=b) = c. Wenn ich im operator= eine Referenz zurückgebe, wird zunächst b an a zugewiesen und dann c an a. Wenn operator= nur ein X zurückgibt, dann wäre nach dieser Zeile a=b (da die Zuweisung von c an eine lokale Kopie stattfindet). Liege ich da richtig?
3. Im Abschnitt 3.10 überlädt er den Postinkrement Operator:
const X X::operator++(int);Wieso gibt er ein KONSTANTES Objekt zurück?
Damit vielleicht SOWAS nicht geht: a++ = c; ? Falls ja: Wieso gibt dann nicht auch das binäre +,-,* etc ein konstantes Objekt zurück?Danke!

-
Ribery@Abflug schrieb:
Hallo,
ich habe mir gerade den Operator Artikel aus dem Magazin ( http://magazin.c-plusplus.net/artikel/�berladung von Operatoren in CPlusPlus (Teil 1) ) durchgelesen und habe (wie zu erwarten) nun ein paar kleine Fragen:
1. Der Autor rät, unäre Operatoren immer als Klassenmethode zu definieren: "Wenn unäre Operatoren nicht als Klassenmethode überladen werden, ist eine implizite Konvertierung des Arguments möglich, was meist ein unerwartetes Feature ist." Das leuchtet mir nicht ein. Wenn ich jetzt eine Klasse rational schreibe und sowas haben will: r1 = -r2; dann würde ich operator- eher als freie Funktion definieren, weil das Objekt selber ja NICHT verändert wird, sondern nur ein verändertes Objekt zurückgegeben wird (wie beim binären +,-,* etc). Kann mir sagen (oder ein Beispiel geben), wieso die unären Operatoren in die Klasse sollten?
Gemeint ist folgendes:
class Y{ /*...*/}; class X { public: X(Y const& other); }; X operator- (X const& arg) {/*...*/} int main() { Y y; X x = -y; //! }y wird hier in ein X konvertiert und dann op- angewandt. Das ist völlig gegen die Intuition die man hat wenn man den Code liest, denn man erwartet eigentlich, dass y einen operator- hat.
2. Sein operator= sieht so aus:
X& X::operator= (X const& rhs);Und er schreibt dazu: "Da kein neues Objekt erzeugt wird, reicht eine Referenz als Rückgabewert, dies ermöglicht Kettenzuweisungen á la a = b = c."
Eine Kettenzuweisung würde doch auch gehen, wenn ich KEINE Referenz zurückgebe, sondern nur ein normales Objekt, alsoX X::operator= (X const& rhs);, oder? Den einzigen Unterschied (neben Effizienz) der Referenz sehe ich hier: (a=b) = c. Wenn ich im operator= eine Referenz zurückgebe, wird zunächst b an a zugewiesen und dann c an a. Wenn operator= nur ein X zurückgibt, dann wäre nach dieser Zeile a=b (da die Zuweisung von c an eine lokale Kopie stattfindet). Liege ich da richtig?
Liegst du. Hauptsächlicher Grund ist aber eben die unnötige erzeugung des temporären Objekts das zurückgegeben wird -> Referenz reicht. Statt einer Referenz void zurückzugeben ist aber eben wegen der Kettenzuweisung nicht so prickelnd.
3. Im Abschnitt 3.10 überlädt er den Postinkrement Operator:
const X X::operator++(int);Wieso gibt er ein KONSTANTES Objekt zurück?
Damit vielleicht SOWAS nicht geht: a++ = c; ? Falls ja: Wieso gibt dann nicht auch das binäre +,-,* etc ein konstantes Objekt zurück?Das ist ne Designentscheidung ob die zurückgegebenen Objekte konstant oder nicht konstant sein sollten. Meistens ist die Veränderung von temporären Objekten allerdings nicht sinnvoll. Zugegebenermaßen war ich da nicht ganz konsistent.
-
Wieso wird beim Zuweisungsoperator eigentlich eine Referenz zurückgegeben? Abgesehen von ein paar wenigen Klassen wie
std::auto_ptrverändern Zuweisungen das Original nicht, also sollte eine Const-Referenz eigentlich reichen...
-
Nexus schrieb:
Wieso wird beim Zuweisungsoperator eigentlich eine Referenz zurückgegeben? Abgesehen von ein paar ganz wenigen Klassen wie
std::auto_ptrverändern Zuweisungen das Original nicht, also sollte eine Const-Referenz eigentlich reichen...Naja, es heißt ja "do it as the ints do". Und bei 3 Integervariablen k,l,m kann man ja auch sowas schreiben: (k=l) = m;
Insofern sehe ich ein, dass alle Zuweisungsoperatoren eine Referenz zurückgeben.
Ich finde jedoch auch eine konstante Referenz wäre ok, da ich Ausdrücke wie (k+=l) = m; ehrlich gesagt für mehr als zweifelhaft finde.Ich fasse mal kurz zusammen:
+ Unäre Operatoren als Klassenmethode
+ Binäre Operatoren (+,-,*,/ etc) als freie Funktion und sie geben ein konstantes Objekt zurück (zb. X operator+(const X& a, const X& b);), damit sowas nicht möglich ist: (a+b) = c;
+ Zuweisungsoperatoren liefern eine Referenz. (Konstante Referenz wäre auch ok).Passt das so?
-
edit: statt
X operator+(const X& a, const X& b)meinte ich natürlich
const X operator+(const X& a, const X& b
-
Ribery@Abflug schrieb:
Ich finde jedoch auch eine konstante Referenz wäre ok, da ich Ausdrücke wie (k+=l) = m; ehrlich gesagt für mehr als zweifelhaft finde.
Sehe ich eben auch so. Zu identifizieren, was so ein Ausdruck macht, braucht wohl einiges länger als
k += l; k = m;Mal völlig abgesehen davon, dass zwei unmittelbar aufeinanderfolgende Zuweisungen an das gleiche Objekt sowieso fragwürdig sind.
-
Nexus schrieb:
Ribery@Abflug schrieb:
Ich finde jedoch auch eine konstante Referenz wäre ok, da ich Ausdrücke wie (k+=l) = m; ehrlich gesagt für mehr als zweifelhaft finde.
Sehe ich eben auch so. Zu identifizieren, was so ein Ausdruck macht, braucht wohl einiges länger als
k += l; k = m;Mal völlig abgesehen davon, dass zwei unmittelbar aufeinanderfolgende Zuweisungen an das gleiche Objekt sowieso fragwürdig sind.
Deswegen schreibt ich auch immer
void operator++();weil schleifen wie
while((*dst++=*src++)!=0);höchst zweifelhaft sind.
manche machen es einfach so, daß es sich wie bei den eingebauten typen anfühlt.
-
Du hast Recht, daran habe ich jetzt nicht gedacht (ich bin jetzt mehr von Kettenzuweisungen mit = ausgegangen). Naja, in 99% der Fälle würde wohl eine Const-Referenz reichen. Aber man verliert ja eigentlich nicht viel, um konsistent zu bleiben...