Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: adam96 en 16 Diciembre 2010, 14:54 pm



Título: sobrecarga de operador<<
Publicado por: adam96 en 16 Diciembre 2010, 14:54 pm
Bueenas. Estoy intentando hacer esto:

Código
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. class MiClase {
  8.  
  9. private:
  10. int num1;
  11. int num2;
  12.  
  13. public:
  14. MiClase(int x=0, int y=0) :
  15. num1(x), num2(y) {}
  16.  
  17.  
  18. // Getters
  19. int getnum1(void) {
  20. return num1;
  21. }
  22.  
  23. int getnum2(void) {
  24. return num2;
  25. }
  26. };
  27.  
  28. ostream& operator<<(ostream& os, const MiClase& miobj) {
  29. cout << miobj.getnum1() << miobj.getnum2();
  30. return os;
  31. }
  32.  
  33. int main(void) {
  34. MiClase miobj(3, 0);
  35.  
  36. cout << miobj;
  37.  
  38.  
  39. return 0;
  40. }
  41.  

El error que me da:
Código:
../src/Test.cpp:29: error: passing ‘const MiClase’ as ‘this’ argument of ‘int MiClase::getnum1()’ discards qualifiers
../src/Test.cpp:29: error: passing ‘const MiClase’ as ‘this’ argument of ‘int MiClase::getnum2()’ discards qualifiers

Alguien me echa una manita?

Gracias anticipadas.


Título: Re: sobrecarga de operador<<
Publicado por: satu en 16 Diciembre 2010, 17:23 pm
Hola no estoy seguro pero creo que deberias hacerlo asi

Código
  1. friend ostream &operator << (ostream& os, const MiClase& miobj)
  2.    {
  3.    os<<miobj.num1<<miobj.num2;
  4.    return os;
  5.    }
  6.  
pero dentro del class

Que algún experto diga por qué no funciona como él lo tiene porque yo no lo sé

Saludos


Título: Re: sobrecarga de operador<<
Publicado por: Littlehorse en 16 Diciembre 2010, 18:39 pm
@Satu:

No, en realidad no es necesario en este caso declarar la definición junto con la declaración puesto que la definición es encontrada.

@adam96

Bienvenido al foro!
Lo que sucede es que utilizas un objeto constante que no puede ser modificado desde miembros que si pueden modificar. Cuando haces esto:

Código
  1. miobj.getnum1()

Estas llamando a getnum1 desde "const MiClase& miobj".
Ahora bien, para solucionarlo, basicamente el procedimiento a seguir es asegurarte que ni getnum1 ni getnum2 van a intentar modificar lo que en un principio no esta puesto para modificarse, -const- y si se esta seguro que nada se va a modificar, se declara la función de esta forma:

Código
  1. int getnum1(void) const {
  2. return num1;
  3. }
  4.  
  5. int getnum2(void) const {
  6. return num2;
  7. }

Que equivale a que getnum1 diga: "Envíame lo que quieras que yo no modifico nada ;D"

El código debería quedarte así:

Código
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. class MiClase {
  8.  
  9. private:
  10. int num1;
  11. int num2;
  12.  
  13. public:
  14. MiClase(int x=0, int y=0) :
  15. num1(x), num2(y) {}
  16.  
  17.  
  18. // Getters
  19. int getnum1(void) const {
  20. return num1;
  21. }
  22.  
  23. int getnum2(void) const {
  24. return num2;
  25. }
  26. };
  27.  
  28. ostream& operator<<(ostream& os, const MiClase& miobj) {
  29. cout << miobj.getnum1() << miobj.getnum2();
  30. return os;
  31. }
  32.  
  33. int main(void) {
  34. MiClase miobj(3, 0);
  35.  
  36. cout << miobj;
  37.  
  38.  
  39. return 0;
  40. }


No lo he probado pero es seguro eso. Cualquier cosa, ya sabes.

Saludos!


Título: Re: sobrecarga de operador<<
Publicado por: satu en 16 Diciembre 2010, 23:49 pm
Muchas gracias LH, no sabia eso. Yo aprendí haciéndolo dentro del .h y no sabia que así también podía hacerse. Gracias de nuevo.

Saludos


Título: Re: sobrecarga de operador<<
Publicado por: adam96 en 17 Diciembre 2010, 12:07 pm
Tengo mas dudas:

Código
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4.  
  5. using namespace std;
  6.  
  7. class MiClase {
  8.  
  9. private:
  10. int num1;
  11. int num2;
  12.  
  13. public:
  14. MiClase(int x=0, int y=0) :
  15. num1(x), num2(y) {}
  16.  
  17. MiClase& operator=(const MiClase& mib) {
  18. num1 = 0;
  19. num2 = 0;
  20. num1 = mib.num1;
  21. num2 = mib.num2;
  22. return *this;
  23. }
  24.  
  25. // Getters
  26. int getnum1(void) const {
  27. return num1;
  28. }
  29.  
  30. int getnum2(void) const {
  31. return num2;
  32. }
  33. };
  34.  
  35. ostream& operator<<(ostream& os, const MiClase& miobj) {
  36. os << miobj.getnum1() << " " << miobj.getnum2();
  37. return os;
  38. }
  39.  
  40. int main(void) {
  41. MiClase a(1, 2), b(3, 4);
  42. cout << "Objeto a: " << a << endl;
  43. a = a;
  44. cout << "Objeto a despues de a = a: " << a << endl;
  45.  
  46.  
  47. return 0;
  48. }
  49.  
  50.  
  51.  

Ese operator<< lo podría opner como método de la clase y que hiciese la misma tarea? A  mi no se me ocurre porque cout no es objeto de Miclase.

Y otra cosa:
Como hago para que en el operador de asignación detecte que se trata del mismo objeto y no lo borre.

Algo como if(*this != objeto_pasado) {el resto del codigo }
Los operadores de comparación no funcionan así :(

Gracias chic@s


Título: Re: sobrecarga de operador<<
Publicado por: Littlehorse en 17 Diciembre 2010, 19:10 pm
Buenas preguntas (https://foro.elhacker.net/Smileys/navidad/cheesy.gif).

Citar
Ese operator<< lo podría opner como método de la clase y que hiciese la misma tarea?

No, no exactamente. Se declara como una función libre siempre que este llamando a otra función que haga la tarea, si no es el caso, se declara como friend de la clase en pos que pueda acceder a los miembros privados.


Citar
Como hago para que en el operador de asignación detecte que se trata del mismo objeto y no lo borre.

Bueno podes hacer varias cosas. Realmente depende de si los usuarios de tu clase van o no van a realizar asignaciones así mismos, aunque lo ideal es pensar que siempre son capaces de hacerlo.
Si no existe la posibilidad que algo así ocurra bajo ningún aspecto, lo mas sencillo es hacer esto:

Código
  1. MiClase& operator=(const MiClase& mib)
  2. {
  3. if (this == &mib)//Mismo objeto?
  4. return *this;//salimos...
  5. num1 = 0;//Y si no, el resto de la logica
  6. num2 = 0;
  7. num1 = mib.num1;
  8. num2 = mib.num2;
  9. return *this;
  10. }

ahora dependiendo de la complejidad de la clase tal vez haya que añadir bastante código extra. Realmente depende del caso en particular.

Saludos!