Jeśli to możliwe, jako osoby niebędące członkami i nieprzyjazne.
Jak opisali Herb Sutter i Scott Meyers, preferuj nieprzyjazne funkcje niebędące członkami od funkcji składowych, aby pomóc zwiększyć hermetyzację.
W niektórych przypadkach, takich jak strumienie C ++, nie będziesz mieć wyboru i musisz używać funkcji niebędących składowymi.
Nie oznacza to jednak, że musisz uczynić te funkcje przyjaciółmi swoich klas: te funkcje mogą nadal uzyskiwać dostęp do Twojej klasy za pośrednictwem metod dostępu do Twojej klasy. Jeśli uda ci się napisać te funkcje w ten sposób, wygrałeś.
O prototypach operatorów << i >>
Uważam, że przykłady, które podałeś w swoim pytaniu, są błędne. Na przykład;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
Nie mogę nawet zacząć myśleć, jak ta metoda mogłaby działać w strumieniu.
Oto dwa sposoby implementacji operatorów << i >>.
Załóżmy, że chcesz użyć obiektu podobnego do strumienia typu T.
I chcesz wyodrębnić / wstawić z / do T odpowiednie dane swojego obiektu typu Paragraf.
Prototypy funkcji operatora ogólnego << i >>
Pierwsza istota jako funkcje:
// 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 ;
}
Operator ogólny << i >> prototypy metod
Druga istota jako metody:
// 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 ;
}
Zauważ, że aby użyć tej notacji, musisz rozszerzyć deklarację klasy T. W przypadku obiektów STL nie jest to możliwe (nie należy ich modyfikować ...).
A co, jeśli T jest strumieniem w C ++?
Oto prototypy tych samych operatorów << i >> dla strumieni C ++.
Dla ogólnych basic_istream i basic_ostream
Zauważ, że jest to przypadek strumieni, ponieważ nie możesz modyfikować strumienia C ++, musisz zaimplementować funkcje. Co oznacza coś takiego:
// 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 ;
}
Dla węgli i ostremów
Poniższy kod będzie działał tylko w przypadku strumieni opartych na znakach.
// 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 skomentował fakt, że kod oparty na znakach jest tylko „specjalizacją” kodu ogólnego nad nim. Oczywiście Rhys ma rację: nie polecam używania przykładu opartego na znakach. Jest tu podane tylko dlatego, że jest łatwiejsze do odczytania. Ponieważ jest to możliwe tylko wtedy, gdy pracujesz tylko ze strumieniami opartymi na znakach, powinieneś unikać go na platformach, na których kod wchar_t jest powszechny (np. W systemie Windows).
Mam nadzieję, że to pomoże.