¿Funciona el operador de sobrecarga << dentro de la clase?
-
27-10-2019 - |
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.
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.