2010-03-16 10 views
5

vorgezogen wird Wenn Sie ein Objekt drucken, wird ein Freund-Operator < < verwendet. Können wir die Elementfunktion für den Operator < < verwenden?Warum die friend-Funktion der Elementfunktion für den Operator <<

class A { 

public: 
void operator<<(ostream& i) { i<<"Member function";} 
friend ostream& operator<<(ostream& i, A& a) { i<<"operator<<"; return i;} 
}; 


int main() { 

    A a; 
    A b; 
    A c; 
    cout<<a<<b<<c<<endl; 
    a<<cout; 
    return 0; 
} 

Ein Punkt ist, dass Freund Funktion, uns ermöglichen, es zu benutzen wie diese

cout<<a<<b<<c 

Welche anderen Gründe?

+3

Brauchen Sie wirklich noch andere Gründe? –

+0

@mmyers: Ich versuche nur, es so klar zu verstehen, wie ich kann. – skydoor

+1

Es kann offensichtlich keine Funktion eines Mitglieds sein (siehe Charles Bailey's Antwort), aber es muss kein * Freund * sein - wenn Sie können es in Bezug auf die öffentliche Schnittstelle der Klasse implementieren, das wäre super. – UncleBens

Antwort

11

Sie müssen eine freie Funktion und keine Elementfunktion verwenden, denn für binäre Operatoren ist die linke Seite immer *this für Elementfunktionen, wobei die rechte Seite als anderer Parameter übergeben wird.

Für Ausgabestream-Operatoren ist die linke Seite immer das Stream-Objekt. Wenn Sie also in eine Standardklasse streamen und den Stream nicht selbst schreiben, müssen Sie eine freie Funktion und kein Mitglied Ihrer Klasse bereitstellen.

Obwohl es möglich wäre, einen Rückwärtsstrom Operator als Member-Funktion zur Verfügung zu stellen und wie dieses ausströmen:

myObject >> std::cout; 

nicht nur verletzen würde man eine sehr starke Bibliothek Konvention, wie Sie darauf hin, Verkettungsausgang Operationen würden aufgrund der Gruppierung von links nach rechts von >> nicht funktionieren.

Edit: Wie andere haben darauf hingewiesen, während Sie es eine kostenlose Funktion machen müssen es braucht nur ein friend zu sein, wenn die Streaming-Funktion nicht in Bezug auf die Klasse öffentliche Schnittstelle implementiert werden kann.

10

Sie haben keine Wahl - es muss eine freie Funktion sein.

Beachten Sie jedoch, dass es sich nicht unbedingt um eine friend Funktion handeln muss. Es muss nur ein Freund sein, wenn Sie ihm einen privaten Zugang gewähren müssen. Zum Beispiel verwende ich die folgende in der Programmierung Wettbewerben

template <class A, class B> 
std::ostream& operator<<(std::ostream& os, const std::pair<A, B>& p) 
{ 
    return os << '(' << p.first << ", " << p.second << ')'; 
} 

Keine Notwendigkeit für ihn Freund zu sein, als first und second sind öffentlich zugänglich.

1

Ein weiterer Grund in Ihrem Beispiel - es muss eine friend sein, denn das ist die einzige Möglichkeit, eine freie Funktion innerhalb der Klassendefinition zu definieren. Wenn Sie eine nicht-freundefreie Funktion wünschen, müsste sie außerhalb der Klasse definiert werden.

Warum würden Sie es am liebsten in der Klasse definieren? Manchmal ist es schön, alle Betreiber zu definieren zusammen:

struct SomeClass { 
    // blah blah blah 
    SomeClass &operator+=(const SomeClass &rhs) { 
     // do something 
    } 
    friend SomeClass operator+(SomeClass lhs, const SomeClass &rhs) { 
     lhs += rhs; 
     return lhs; 
    } 
    // blah blah blah 
    // several pages later 
}; 

könnte ein bisschen mehr benutzerfreundlicher als:

struct SomeClass { 
    // blah blah blah 
    SomeClass &operator+=(const SomeClass &rhs) { 
     // do something 
    } 
    // blah blah blah 
    // several pages later 
}; 

SomeClass operator+(SomeClass lhs, const SomeClass &rhs) { 
    lhs += rhs; 
    return lhs; 
} 

Dies setzt voraus, natürlich, dass Sie die entsprechenden Member-Funktionen in der Klassendefinition definieren Stattdessen deklarieren sie sie und definieren sie in einer CPP-Datei.

Bearbeiten: Ich habe + = und + als Beispiel ohne wirklich darüber nachzudenken, aber Ihre Frage ist über operator<<, die keine eng verwandten Operatoren wie operator+ hat. Wenn jedoch operator<< eine oder mehrere Mitgliedsfunktionen zum Drucken aufruft, möchten Sie diese möglicherweise in der Nähe ihrer Definition definieren.

0

Sie können nicht. Aber wenn Sie nicht wollen, dass es eine Friend-Funktion ist, machen Sie es zu einer freien Funktion und implementieren Sie es in Bezug auf die öffentliche Schnittstelle der Klasse. Für z.

ostream& operator<<(ostream& os, Myclass& obj) 
{ 
    return obj.print(os); 
} 

ostream& MyClass::print(ostream& os) 
{ 
    os << val; // for example. 
    return os; 
}