Operatorenüberladung
-
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 }