Pregunta

Quiero decir, estaba tratando de sobrecargar el operador << dentro de la clase

como esto

 class A {
      public:
           ostream &operator<<(ostream &os);// which doesnt work

      private:
           friend ostream &operator<<(ostream &os, const A& a); //Works
           int i;

 };

  Definition
          ostream &operator<<(ostream &os, const A& a) {
              os<<a.i;
              return os;
          }

¿Por qué no puedo sobrecargar el operador dentro de la clase específica para la clase? ¿O me estoy perdiendo algo? ¿O soy estúpido incluso pensar de esa manera? Por favor avise.

¿Fue útil?

Solución

La función miembro:

ostream &operator<<(ostream &os);

lo hace Trabaja, pero no para la situación que deseas. Se llamará cuando hagas algo como:

A a;
a << std::cout;

es decir, donde el objeto es el lado izquierdo del operador.

Otros consejos

El problema es que tu operator<< Tomaría ostream Como segundo parámetro, no es el primero. De esa manera, podrías hacer myObject << std::cout, pero se vería poco intuitivo y no podrías encadenar llamadas debido a operator<< Ser asociativo de la izquierda.

Otro beneficio de declarar al operador como amigo en lugar de una función miembro es que pueden ocurrir conversiones automáticas. Eso significa que si tienes una clase B que no deriva de A pero tiene un B(A const&) constructor, aún podrás hacer std::cout << my_b; y tenerlo convertido a un A y luego impreso.

Afortunadamente, definiendo operator<< Como un amigo se puede hacer dentro de la clase si lo prefiere. Su código podría escribirse como

class A {
    int i;
    friend std::ostream& operator<<(std::ostream& o, A const& a) {
        o << a.i;
        return o;
    }
};

¿Por qué el estándar no le permite especificar qué lado debe continuar el argumento? Fingimos que lo hizo y agregamos el left_of y right_of Palabras clave para especificar:

struct B;

struct A {
     A left_of operator+(B const&) {
         return *this;
     }
};

struct B {
     B right_of operator+(A const&) {
         return *this;
     }
};

¿Qué pasa ahora cuando lo hacemos? A a; B b; f(a + b);? Cada clase tiene un operador que maneja este caso, lo que significa que no podemos decidir. De todos modos, ver que muchos operadores deberían ser amigos debido a las posibilidades de conversión, no permitir este tipo de cosas no es un problema tan grande y evita este tipo de ambigüedades. (Por supuesto, también podría definir un operador miembro y uno gratuito, lo que causaría un problema muy similar).

Por cierto, como son las cosas, la definición de tu friend operator<< no está devolviendo nada, lo que arruinará la encadenación.

Recuerde que para una función miembro no estática de un primer argumento de clase es este puntero. Entonces, la firma de su función "operador <<", después de la compilación, se convertirá:

ostream &operator<<(A *this, ostream &os);

Esto funcionará cuando hagas algo como:

A obj;
obj << std::cout;

Piense en "obj" como primer argumento y "std :: cout" como segundo argumento para el operador "<<".

Una mejor manera de sobrecargar "<<" es usar la función de amigos porque de esta manera puede hacer que su operador sobrecargado sea asociativo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top