Funktioniert der Operator << in der Klasse?
-
27-10-2019 - |
Frage
Ich meine, ich habe versucht, den Operator << in der Klasse zu überladen
so was
class A {
public:
ostream &operator<<(ostream &os);// which doesnt work
private:
friend ostream &operator<<(ostream &os, const A& a); //Works
int i;
};
Definition
ostream &operator<<(ostream &os, const A& a) {
os<<a.i;
return os;
}
Warum kann ich den Operator nicht in der Klasse, die für die Klasse spezifisch ist, überlasten? Oder vermisst ich etwas? Oder bin ich dumm, überhaupt so zu denken? Bitte beraten.
Lösung
Die Mitgliedsfunktion:
ostream &operator<<(ostream &os);
tut Arbeit, aber nicht für die Situation, die Sie wollen. Es wird aufgerufen, wenn Sie so etwas tun wie:
A a;
a << std::cout;
dh wo das Objekt die linke Seite des Bedieners ist.
Andere Tipps
Das Problem ist, dass Ihre operator<<
würde nehmen ostream
Als zweiter Parameter nicht als erster. Auf diese Weise könnten Sie tun myObject << std::cout
, aber es würde unintuitiv aussehen und Sie würden keine Anrufe anketten können operator<<
links zu assoziativ sein.
Ein weiterer Vorteil der Erklärung des Bedieners als Freund im Gegensatz zu einer Mitgliedsfunktion besteht darin, dass automatische Konvertierungen auftreten können. Das heißt, wenn Sie eine Klasse haben B
das leitet sich nicht aus A
hat aber eine B(A const&)
Konstruktor können Sie noch tun std::cout << my_b;
und lassen es zu einem konvertiert A
und dann gedruckt.
Zum Glück definieren operator<<
Als Freund kann innerhalb der Klasse erledigt werden, wenn Sie es vorziehen. Ihr Code könnte geschrieben werden als
class A {
int i;
friend std::ostream& operator<<(std::ostream& o, A const& a) {
o << a.i;
return o;
}
};
Warum erlaubt der Standard nicht, dass Sie angeben, auf welcher Seite das Argument stattfinden soll? Stellen wir uns so aus, left_of
und right_of
Schlüsselwörter, um anzugeben:
struct B;
struct A {
A left_of operator+(B const&) {
return *this;
}
};
struct B {
B right_of operator+(A const&) {
return *this;
}
};
Was passiert jetzt, wenn wir es tun? A a; B b; f(a + b);
? Jede Klasse hat einen Bediener, der diesen Fall behandelt, was bedeutet, dass wir uns nicht entscheiden können. Da viele Betreiber aufgrund der Konversionsmöglichkeiten ohnehin Freunde sein sollten, ist es kein großes Problem, so etwas zuzulassen, und verhindert diese Art von Unklarheiten. (Natürlich können Sie auch einen und ein kostenlosen Mitgliedsbetreiber definieren, was ein sehr ähnliches Problem verursachen würde.)
Übrigens wie die Dinge die Definition Ihrer friend operator<<
Nicht zurückzugeben, was die Verkettung durcheinander bringt.
Denken Sie daran, dass für eine nicht statische Mitgliedsfunktion eines ersten Arguments dieser Zeiger ist. Die Signatur Ihrer Funktion "Operator <<" nach der Zusammenstellung wird also:
ostream &operator<<(A *this, ostream &os);
Dies wird funktionieren, wenn Sie so etwas tun:
A obj;
obj << std::cout;
Stellen Sie sich "Obj" als erstes Argument und "std :: cout" als 2. Argument für den Operator "<<" vor.
Bessere Möglichkeit, "<<" zu überlasten, besteht darin, die Freundschaftsfunktion zu verwenden, da Sie auf diese Weise Ihren überlasteten Operator assoziativ machen können.