Si possible, en tant que non-membre et non-amis fonctions de.
Comme décrit par Herb Sutter et Scott Meyers, préférez les non-ami non membre de fonctions de fonctions membres, pour aider à augmenter l'encapsulation.
Dans certains cas, comme en C++ flux, vous n'aurez pas le choix et doit utiliser des fonctions membres.
Mais encore, cela ne signifie pas que vous avez à faire ces fonctions les amis de vos classes: Ces fonctions peuvent toujours accéder à votre classe par le biais de votre classe accesseurs. Si vous réussissez dans l'écriture de ces fonctions de cette façon, alors vous avez gagné.
À propos de l'opérateur << et >> les prototypes
Je crois que les exemples que vous citez dans votre question sont mauvais. Par exemple;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
Je ne peux même pas commencer à penser à la façon dont cette méthode pourrait fonctionner dans un ruisseau.
Voici les deux façons de mettre en œuvre les << et >> les opérateurs.
Disons que vous voulez utiliser un flux-comme objet de type T.
Et que vous voulez extraire d'insertion/de/en T les données pertinentes de votre objet de type Point.
Générique de l'opérateur << et >> les prototypes de fonction
La première étant que les fonctions de:
// 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 ;
}
Générique de l'opérateur << et >> méthode de prototypes
La seconde étant que les méthodes:
// 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 ;
}
Notez que pour utiliser cette notation, vous devez étendre T de la déclaration de classe. Pour STL objets, ce n'est pas possible (vous n'êtes pas censé modifier...).
Et si T est un C++ stream?
Voici les prototypes de la même << et >> les opérateurs en C++ ruisseaux.
Pour générique basic_istream et basic_ostream
Notez que c'est le cas de cours d'eau, que vous ne pouvez pas modifier le C++ flux, vous devez implémenter les fonctions. Ce qui signifie quelque chose comme:
// 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 ;
}
Pour char istream et ostream
Le code suivant ne fonctionne que pour le char à base de flux.
// 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 a commenté sur le fait que le char à base de code mais une "spécialisation" de l'génériques de code ci-dessus. Bien sûr, Rhys est juste: je ne recommande pas l'utilisation de la char-base exemple. Il n'est donné ici parce que c'est plus simple à lire. Comme il n'est viable seulement si vous travaillez avec char à base de flux, vous devriez éviter sur les plates-formes où wchar_t code commun (c'est à dire sur Windows).
Espérons que cela aidera.