Si es posible, como no miembro y no amigo funciones.
Como lo describieron Herb Sutter y Scott Meyers, prefieren las funciones no miembros no amigos a las funciones miembros, para ayudar a aumentar la encapsulación.
En algunos casos, como las transmisiones de C ++, no tendrá la opción y deberá usar funciones que no sean miembros.
Pero aún así, no significa que tenga que hacer que estas funciones sean amigas de sus clases: estas funciones aún pueden acceder a su clase a través de sus accesos de clase. Si logra escribir esas funciones de esta manera, entonces ganó.
Sobre el operador << y >> prototipos
Creo que los ejemplos que dio en su pregunta están equivocados. Por ejemplo;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
Ni siquiera puedo empezar a pensar cómo podría funcionar este método en una secuencia.
Estas son las dos formas de implementar los operadores << y >>.
Digamos que desea utilizar un objeto similar a una secuencia del tipo T.
Y que desea extraer / insertar de / en T los datos relevantes de su objeto de tipo Párrafo.
Operador genérico << y >> prototipos de funciones
El primer ser como funciones:
// 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 ;
}
Operador genérico << y >> prototipos de métodos
El segundo ser como métodos:
// 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 ;
}
Tenga en cuenta que para usar esta notación, debe extender la declaración de clase de T. Para los objetos STL, esto no es posible (se supone que no debe modificarlos ...).
¿Y si T es un flujo de C ++?
Aquí están los prototipos de los mismos operadores << y >> para flujos C ++.
Para genérico basic_istream y basic_ostream
Tenga en cuenta que es el caso de las secuencias, ya que no puede modificar la secuencia de C ++, debe implementar las funciones. Lo que significa algo como:
// 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 ;
}
Para char istream y ostream
El siguiente código funcionará solo para transmisiones basadas en caracteres.
// 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 comentó sobre el hecho de que el código basado en caracteres no es más que una "especialización" del código genérico sobre él. Por supuesto, Rhys tiene razón: no recomiendo el uso del ejemplo basado en char. Solo se da aquí porque es más fácil de leer. Como solo es viable si solo trabaja con secuencias basadas en char, debe evitarlo en plataformas donde el código wchar_t es común (es decir, en Windows).
Espero que esto ayude.