Wenn möglich, als Nichtmitglied und Nichtfreund.
Wie von Herb Sutter und Scott Meyers beschrieben, bevorzugen Sie Funktionen von Nicht-Freunden, die keine Mitglieder sind, gegenüber Funktionen von Mitgliedern, um die Kapselung zu verbessern.
In einigen Fällen, wie bei C ++ - Streams, haben Sie keine Wahl und müssen Funktionen verwenden, die keine Mitglieder sind.
Dies bedeutet jedoch nicht, dass Sie diese Funktionen zu Freunden Ihrer Klassen machen müssen: Diese Funktionen können Ihre Klasse weiterhin über Ihre Klassenzugriffsberechtigten erreichen. Wenn es Ihnen gelingt, diese Funktionen auf diese Weise zu schreiben, haben Sie gewonnen.
Über Operator << und >> Prototypen
Ich glaube, die Beispiele, die Sie in Ihrer Frage gegeben haben, sind falsch. Beispielsweise;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
Ich kann mir gar nicht vorstellen, wie diese Methode in einem Stream funktionieren könnte.
Hier sind die beiden Möglichkeiten, die Operatoren << und >> zu implementieren.
Angenommen, Sie möchten ein Stream-ähnliches Objekt vom Typ T verwenden.
Und dass Sie die relevanten Daten Ihres Objekts vom Typ Paragraph aus / in T extrahieren / einfügen möchten.
Generische Operator << und >> Funktionsprototypen
Das erste ist als Funktionen:
// T << Paragraph
T & operator << (T & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// T >> Paragraph
T & operator >> (T & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return p_oInputStream ;
}
Generische Prototypen der Operatormethoden << und >>
Das zweite ist als Methoden:
// T << Paragraph
T & T::operator << (const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return *this ;
}
// T >> Paragraph
T & T::operator >> (const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return *this ;
}
Beachten Sie, dass Sie zur Verwendung dieser Notation die Klassendeklaration von T erweitern müssen. Für STL-Objekte ist dies nicht möglich (Sie sollten sie nicht ändern ...).
Und was ist, wenn T ein C ++ - Stream ist?
Hier sind die Prototypen derselben << und >> Operatoren für C ++ - Streams.
Für generischen basic_istream und basic_ostream
Beachten Sie, dass dies bei Streams der Fall ist, da Sie den C ++ - Stream nicht ändern können. Sie müssen die Funktionen implementieren. Was so etwas bedeutet wie:
// OUTPUT << Paragraph
template <typename charT, typename traits>
std::basic_ostream<charT,traits> & operator << (std::basic_ostream<charT,traits> & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> Paragraph
template <typename charT, typename traits>
std::basic_istream<charT,traits> & operator >> (std::basic_istream<charT,traits> & p_oInputStream, const CMyObject & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
Für char istream und ostream
Der folgende Code funktioniert nur für char-basierte Streams.
// OUTPUT << A
std::ostream & operator << (std::ostream & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> A
std::istream & operator >> (std::istream & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
Rhys Ulerich kommentierte die Tatsache, dass der char-basierte Code nur eine "Spezialisierung" des darüber liegenden generischen Codes ist. Natürlich hat Rhys Recht: Ich empfehle die Verwendung des char-basierten Beispiels nicht. Es wird hier nur gegeben, weil es einfacher zu lesen ist. Da dies nur möglich ist, wenn Sie nur mit char-basierten Streams arbeiten, sollten Sie dies auf Plattformen vermeiden, auf denen wchar_t-Code häufig vorkommt (z. B. unter Windows).
Hoffe das wird helfen.