Operatorenüberladung
-
danke, nur wieso deklarierst du die funktion als friend? ich kann da jetzt keine vorteile sehen.
-
Weil er mit der Funktion auf einen Member zugreift der privat ist?
-
MarcoYolo schrieb:
Weil er mit der Funktion auf einen Member zugreift der privat ist?
auf den die Methode aber sowieso Zugriff hat, wenn sie - wie hier - zu der Klasse gehört?
-
wo denn?
Edit:
eben!
-
ok, frage besser gestellt: gibt es irgendeinen grund die funktion als friend zu deklarieren wenn ich das inline nicht benötige?
-
n000000b schrieb:
ok, frage besser gestellt: gibt es irgendeinen grund die funktion als friend zu deklarieren wenn ich das inline nicht benötige?
Ja! Das hat nichts mit inline oder nicht zu tun. Das inline ist hier extra. Daher gilt die alte Antwort:
MarcoYolo schrieb:
Weil er mit der Funktion auf einen Member zugreift der privat ist?
daddy_felix schrieb:
auf den die Methode aber sowieso Zugriff hat, wenn sie - wie hier - zu der Klasse gehört?
Gehört sie aber nicht. Das ist mit dieser Schreibweise keine Memberfunktion, sondern eine freie Funktion im Namespace der Klasse. Merkst du schon an der Schreibweise, denn was wäre hier denn das this-Objekt?
-
daddy_felix schrieb:
MarcoYolo schrieb:
Weil er mit der Funktion auf einen Member zugreift der privat ist?
auf den die Methode aber sowieso Zugriff hat, wenn sie - wie hier - zu der Klasse gehört?
Welche Methode? Ich sehe keine. Ich sehe nur eine freie Funktion, die eben genau deshalb (KEINE Methode aber private-Zugriff) zum
potentiellen Vergewaltigerfriend ernannt wurde.@n000000b: Schau mal oben ins Magazin, da gibts einen Artikel zur Operatorüberladung - der behandelt auch op>>. Und vielleicht (nur so als Anregung) solltest du dir einen anderen Namen überlegen, wenn du hier Fragen stellst - dann hast du auch Chancen, ernst genommen zu werden

-
Man kann es auch mit einer Gegenfrage beantworten:
Wie würde die Syntax aussehen wenn man versucht den Rechts-Shift-Operator mit zwei Argumenten aufzurufen?
-
SeppJ schrieb:
daddy_felix schrieb:
auf den die Methode aber sowieso Zugriff hat, wenn sie - wie hier - zu der Klasse gehört?
Gehört sie aber nicht. Das ist mit dieser Schreibweise keine Memberfunktion, sondern eine freie Funktion im Namespace der Klasse. Merkst du schon an der Schreibweise, denn was wäre hier denn das this-Objekt?
ah cool, wieder was gelernt, danke. Wusste noch gar nicht, dass sowas geht.
MarcoYolo schrieb:
Man kann es auch mit einer Gegenfrage beantworten:
Wie würde die Syntax aussehen wenn man versucht den Rechts-Shift-Operator mit zwei Argumenten aufzurufen?hm... so:
anObject.operator>>(myStream, myObject);
und ja, ich habe verstanden, worauf du hinauswolltest.
-
Hä?
Normalerweise schreibt man folgendes:
class Foo { int x; }; std::istream& operator>>(std::istream& is, Foo & o) { // .. blabla return is; }Da man aber jetzt nicht auf die Member zugreifen kann, gibt es saubere 2 Möglichkeiten:
Nummer1:class Foo { int x; public: void read(std::istream & is) { is >> this->x; } }; std::istream& operator>>(std::istream& is, Foo & o) { o.read(is); return is; }Oder halt das hier:
class Foo { int x; public: friend std::istream& operator>>(std::istream& is, Foo & o); }; std::istream& operator>>(std::istream& is, Foo & o) { is >> o.x; return is; }Den Zugriff hier extra über Getter/Setter zu steuern halte ich in solchen Fällen für Schwachsinn.
Das Inline im ersten Beispiel war alleine dazu da, etwaige Linkerfehler (Mehrfachdefinition) auszuhebeln, so aus Spass.
Und wie z.B. Pumuckl schon sagte, es gibt eine Klasse und eine freie Funktion, die aber ein Freund der Klasse ist. Nix mit Memberfunktion...
Einen Rightshift Operator mit 2(bzw. 3 wie mein Vorredner gerne hätte) Parametern gibt es nicht.
-
SeppJ schrieb:
daddy_felix schrieb:
auf den die Methode aber sowieso Zugriff hat, wenn sie - wie hier - zu der Klasse gehört?
Gehört sie aber nicht. Das ist mit dieser Schreibweise keine Memberfunktion, sondern eine freie Funktion im Namespace der Klasse.
Jo - aber wo geht dann dieser Zugriff auf 'myMember' hin:
Skym0sh0 schrieb:
class MyClass { int myMember; public: friend inline std::istream& operator>>(std::istream& is, MyClass& x) { // hier arbeiten, wie z.B. is >> myMember; return is; } };
-
Belli schrieb:
Jo - aber wo geht dann dieser Zugriff auf 'myMember' hin:
Nirgendwohin, das compiliert nämlich nicht, Flüchtigkeitsfehler von Skym0sh0.
x.myMembermuss es heißen.P.S.: Dieser Fehler passiert mir übrigens auch dauernd, egal wo genau ich den Operator definiere. Er fühlt sich einfach wie ein Klassenmember an. Wenn ich mal eine obskure Programmiersprache entwickele, dann werden Ausdrücke von links nach rechts ausgewertet und man schreibt dann
wert3 << wert2 << wert1 << cin;Ganz intuitiv

-
Ups, verschrieben. War ungetestet und aus dem handgelenk geschüttelt.
Das ist falsch so, das muss sich natürlich auf das myMember von x beziehen:
class MyClass { int myMember; public: friend inline std::istream& operator>>(std::istream& is, MyClass& x) { // hier arbeiten, wie z.B. is >> x.myMember; return is; } };
-
Skym0sh0 schrieb:
Ups, verschrieben. War ungetestet und aus dem handgelenk geschüttelt.
Das ist falsch so, das muss sich natürlich auf das myMember von x beziehen:
dann ist es auch schon eher als freie Funktion erkennbar...
-
SeppJ schrieb:
[...]
P.S.: Dieser Fehler passiert mir übrigens auch dauernd, egal wo genau ich den Operator definiere. Er fühlt sich einfach wie ein Klassenmember an.
Tja, was soll ich sagen ...
Ohne Deinen Hinweis, dass es sich um eine freie Funktion im Namespace der Klasse handelt, hätte ich steif und fest behauptet, dass es eine Memberfunktion/Methode ist, weil sie eben in der Klasse definiert ist ...Wodurch wird sie 'frei'? Durch das Schlüsselwort 'friend'?
Und kann man sie einfach wie gewohnt nutzen, obwohl sie in einem Namespace liegt? Wird das durch die für mich viel zu undurchsichtigen Namelookup-Regeln gewährleistet, weil ja ein Objekt vom Typ der Klasse beteiligt ist?
-
Belli schrieb:
Wodurch wird sie 'frei'? Durch das Schlüsselwort 'friend'?
Ja.
Und kann man sie einfach wie gewohnt nutzen, obwohl sie in einem Namespace liegt? Wird das durch die für mich viel zu undurchsichtigen Namelookup-Regeln gewährleistet, weil ja ein Objekt vom Typ der Klasse beteiligt ist?
Ja.
Mal die relevanten Stellen im Standard (Kapitelangaben C++11, in C++98 ist es nicht (oder nicht großartig) anders):
11.3,6-7 schrieb:
A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8),
the function name is unqualified, and the function has namespace scope.
Example:class M { friend void f() { } // definition of global f, a friend of M, // not the definition of a member function };Such a function is implicitly
inline. A friend function defined in a class is in the (lexical) scope of the
class in which it is defined. A friend function defined outside the class is not (3.4.1).Wir sehen auch: Das inline war überflüssig.
-
Okay, dann hab ich das zumindest im Nachhinein ja richtig verstanden.
Das hier:SeppJ schrieb:
A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not (3.4.1).
ist dann nicht von praktischer Relevanz, weil ich das als Nutzer der Klasse oder der Funktion nicht bemerke, sondern unabhängig davon (scope of the class, oder eben auch nicht) auf die gleiche Weise benutzen kann?
-
Belli schrieb:
ist dann nicht von praktischer Relevanz, weil ich das als Nutzer der Klasse oder der Funktion nicht bemerke, sondern unabhängig davon (scope of the class, oder eben auch nicht) auf die gleiche Weise benutzen kann?
Meistens ist es egal.
Murphys Gesetz: Irgendwann wird natürlich gerade der Fall eintreten, mit dem man nie rechnet und du möchtest einen Zeiger oder sonst etwas auf diese Funktion, wobei es dann schiefgeht:#include <iostream> class Foo { friend std::ostream& func(std::ostream &out, const Foo&){ return out; } }; class Bar { friend std::ostream& operator<<(std::ostream &out, const Bar&); }; class FooBar { friend std::ostream& operator<<(std::ostream &out, const FooBar&); }; std::ostream& operator<<(std::ostream &out, const Bar&){ return out; } std::ostream& operator<<(std::ostream &out, const FooBar&){ return out; } int main() { std::ostream& (*bar_ptr)(std::ostream &out, const Bar&) = operator<<; // Geht std::ostream& (*foobar_ptr)(std::ostream &out, const FooBar&) = operator<<; // Dito. Ist schließlich das gleiche, ich wollte bloß die // Überladungsauflösung demonstrieren std::ostream& (*foo_ptr)(std::ostream &out, const Foo&) = operator<<; // Kann Funktion nicht finden }Was mich nun jedoch in die etwas unrühmliche Situation bringt, dass ich selber nicht weiß, wie man jemals an einen Zeiger auf eine so definierte Funktion kommt.
-
Du kannst func nicht finden, indem Du nach << suchst?
-
volkard schrieb:
Du kannst func nicht finden, indem Du nach << suchst?
Ups, eine Zeile habe ich nicht geändert, vorm posten. So soll das Beispiel aussehen:
#include <iostream> class Foo { friend std::ostream& operator<<(std::ostream &out, const Foo&){ return out; } }; class Bar { friend std::ostream& operator<<(std::ostream &out, const Bar&); }; class FooBar { friend std::ostream& operator<<(std::ostream &out, const FooBar&); }; std::ostream& operator<<(std::ostream &out, const Bar&){ return out; } std::ostream& operator<<(std::ostream &out, const FooBar&){ return out; } int main() { std::ostream& (*bar_ptr)(std::ostream &out, const Bar&) = operator<<; // Geht std::ostream& (*foobar_ptr)(std::ostream &out, const FooBar&) = operator<<; // Dito. Ist schließlich das gleiche, ich wollte bloß die // Überladungsauflösung demonstrieren std::ostream& (*foo_ptr)(std::ostream &out, const Foo&) = operator<<; // Kann Funktion nicht finden }