Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] [Sobrecarga de operadores] Explicación de sobre código

Estas en el tema de [Sobrecarga de operadores] Explicación de sobre código en el foro de C/C++ en Foros del Web. ¡Hola a todos!, soy yo de vuelta y vuelvo a quitarles un poco de tiempo para pedirles ayuda con un código que he escrito para ...
  #1 (permalink)  
Antiguo 28/05/2013, 03:35
Avatar de Doommarine_Maxi  
Fecha de Ingreso: febrero-2011
Mensajes: 54
Antigüedad: 13 años, 10 meses
Puntos: 8
[Sobrecarga de operadores] Explicación de sobre código

¡Hola a todos!, soy yo de vuelta y vuelvo a quitarles un poco de tiempo para pedirles ayuda con un código que he escrito para practicar sobrecarga de operadores.

Como casi todos los que recién inician en el manejo serio de clases, mi primer clase es de una cadena, si, poco original.

Código C++:
Ver original
  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5.  
  6. using namespace std;
  7.  
  8. /*Clase Cadena*/
  9.  
  10. class Cadena
  11. {
  12.     public:
  13.         Cadena(); /*Constructor default*/
  14.         Cadena(const char*); /*Sobrecarga de constructor con parametro puntero a char (array) constante*/
  15.         Cadena &operator=(const Cadena&); /*Sobrecarga de Operador = con parametro Cadena mediante referencia y constante*/
  16.         Cadena &operator=(const char*); /*Sobrecarga de Operador = con parametro puntero a char (array) constante*/
  17.         Cadena operator+(const Cadena&); /*Sobrecarga de Operador + con parametro Cadena mediante referencia y constante*/
  18.         Cadena operator+(const char*); /*Sobrecarga de Operador + con parametro puntero a char (array) constante*/
  19.         //~Cadena() { delete [] cad; }; //Este destructor me generaba problemas en ejecución
  20.         void Mostrar() { cout << cad << endl; }
  21.     private:
  22.         char* cad; /*Puntero a cadena que va a funcionar como un array*/
  23. };
  24.  
  25. Cadena::Cadena()
  26. {
  27.     /*En caso default de declaración de cadena el valor de cad es nulo*/
  28.     cad = NULL;
  29. }
  30. Cadena::Cadena(const char* cadena)
  31. {
  32.     /*Asigno el valor de cadena a cad*/
  33.     this->cad = new char[strlen(cadena)+1]; /*Reservo a un espacio de la memoria equivalente a la cantidad de
  34.     caracteres en la cadena parametro más 1 para el caracter nulo que marca el final de cadena*/
  35.     strcpy(this->cad, cadena);
  36. }
  37.  
  38. /*La función sobrecarga de operator= en tipo de dato Cadena devuelve la dirección de la memoria
  39. del valor que da como retorno esta función*/
  40. Cadena &Cadena::operator=(const Cadena &CadC)
  41. {
  42.     if (this == &CadC)
  43.         return *this;
  44.     if (!CadC.cad)
  45.         return *this;
  46.  
  47.     delete [] this->cad;
  48.     this->cad = new char[strlen(CadC.cad)+1];
  49.     strcpy(this->cad, CadC.cad);
  50.     return *this; /*Devulevo el valor de la cadena actual a la que le asigne el "cad" de CadC
  51.     , este valor luego, debido a &Cadena::..., pasa en realidad la dirección de memoria de *this, que es this*/
  52. }
  53.  
  54. Cadena &Cadena::operator=(const char* C)
  55. {
  56.     if (!C)
  57.         return *this;
  58.  
  59.     delete [] this->cad;
  60.     this->cad = new char[strlen(C)+1];
  61.     strcpy(this->cad, C);
  62.     return *this;
  63. }
  64.  
  65. /*En estas funciones, la sobrecarga del operador+ esta el problema del desbordamiento al usar
  66. la propiedad del destructor de cadena para liberar la memoria reservada por "cad"*/
  67. Cadena Cadena::operator+(const Cadena &CadC)
  68. {
  69.     if (!CadC.cad)
  70.         return *this;
  71.     Cadena temp;   
  72.     temp.cad = new char[strlen(CadC.cad)+strlen(this->cad)+1];
  73.     strcpy(temp.cad, this->cad);
  74.     strcat(temp.cad, CadC.cad);
  75.  
  76.     return temp;
  77. }
  78. Cadena Cadena::operator+(const char *C)
  79. {
  80.     if (!C)
  81.         return *this;
  82.  
  83.     Cadena temp;   
  84.     temp.cad = new char[strlen(C)+strlen(this->cad)+1];
  85.     strcpy(temp.cad, this->cad);
  86.     strcat(temp.cad, C);
  87.  
  88.     return temp;
  89. }
  90.  
  91. int main()
  92. {
  93.     Cadena H("Hola mundo");
  94.     Cadena *J;
  95.     Cadena *K;
  96.     K = &H;
  97.            
  98.     J = new Cadena[3];
  99.     J[0] = "Hola ";
  100.     J[1] = "mis ";
  101.     J[2] = "Amigos.";
  102.    
  103.     for (int x=0; x < 3; x++) J[x].Mostrar();
  104.  
  105.     H.Mostrar();
  106.     H = "Hola a todos";
  107.     H.Mostrar();
  108.     H = H + (H + " Chau");
  109.     H.Mostrar();
  110.  
  111.     *K = J[0] + J[1] + J[2];
  112.     H.Mostrar();
  113.  
  114.     delete [] J;
  115.    
  116.     return 0;
  117. }

Me gustaría que me puedan ayudar a saber cual es el error que cometo en la sobrecarga del operador+ en tipo de clase Cadena, que tal es el problema que si activo el destructor se genera un error durante la ejecución.

Muchas gracias, también me gustaría, y esto es opcional y se los agradecería mucho, si me pudieran decir si esta bien comentado mi código, o si estoy cometiendo algún error al interpretar las referencias o los punteros.
  #2 (permalink)  
Antiguo 28/05/2013, 04:07
 
Fecha de Ingreso: julio-2012
Mensajes: 375
Antigüedad: 12 años, 5 meses
Puntos: 28
Respuesta: [Sobrecarga de operadores] Explicación de sobre código

Los comentarios los veo correctos. Aunque en un código profesional habría que poner la definición y implementación en archivos distintos (por cuestión de orden y mantener el encapsulamiento).

Los operadores + no son correctos porque estás creando nuevas clases sobre la marcha. Has perdido la referencia de la clase original, tienes que devolver la misma clase.

Yo lo haría directo:

Código C++:
Ver original
  1. Cadena Cadena::operator+(const char *C)
  2. {
  3.     if (!C)
  4.         return *this;
  5.    
  6.     delete [] cad; // Borramos la antigua cadena
  7.     cad = new char[strlen(C)+strlen(this->cad)+1]; // creamos una nueva
  8.     strcat(cad,C);
  9.  
  10.     return *this;
  11. }

Nota: No es necesario usar el puntero this para acceder al miembro cad de la clase.

Última edición por amchacon; 28/05/2013 a las 04:12
  #3 (permalink)  
Antiguo 28/05/2013, 04:21
Avatar de Doommarine_Maxi  
Fecha de Ingreso: febrero-2011
Mensajes: 54
Antigüedad: 13 años, 10 meses
Puntos: 8
Respuesta: [Sobrecarga de operadores] Explicación de sobre código

Cita:
Iniciado por amchacon Ver Mensaje
Los comentarios los veo correctos. Aunque en un código profesional habría que poner la definición y implementación en archivos distintos (por cuestión de orden y mantener el encapsulamiento).

Los operadores + no son correctos porque estás creando nuevas clases sobre la marcha. Has perdido la referencia de la clase original, tienes que devolver la misma clase.

Yo lo haría directo:

Código C++:
Ver original
  1. Cadena Cadena::operator+(const char *C)
  2. {
  3.     if (!C)
  4.         return *this;
  5.    
  6.     delete [] cad; // Borramos la antigua cadena
  7.     cad = new char[strlen(C)+strlen(this->cad)+1]; // creamos una nueva
  8.     strcat(cad,C);
  9.  
  10.     return *this;
  11. }

Nota: No es necesario usar el puntero this para acceder al miembro cad de la clase.

Muchas gracias por tu comentario amchacon, me gustaría consultarte una ultima cosa.

Veras, recien estoy empezando a manejarme con punteros de una manera, digamos "más prolija". He visto que has usado la función new para reservar más espacio en la memoria dinámica para datos tipo char. La consulta aquí es que...

Al utilizar new, ¿Simplemente se reserva más espacio en la memoria sin afectar a los datos que hay en ella?, es decir, ¿Todos los datos que hay en "cad" siguen intactos con la diferencía que ahora tengo más espació en los arrays verdad?, ¿como un "realloc"?.

Otra cosa, delete [], lo que hace es eliminar la reserva de espació en la memoria y new genera nueva reserva de espació en la memoria dinamica... ¿Todo sin afectar a los datos que había en esos espacios de memoria verdad?.

Simplemente tengo esa duda al ver que usaste delete, luego new y luego concatenaste a cad

Última edición por Doommarine_Maxi; 28/05/2013 a las 04:22 Razón: Faltas de ortografía
  #4 (permalink)  
Antiguo 28/05/2013, 05:35
 
Fecha de Ingreso: julio-2012
Mensajes: 375
Antigüedad: 12 años, 5 meses
Puntos: 28
Respuesta: [Sobrecarga de operadores] Explicación de sobre código

Cita:
Iniciado por Doommarine_Maxi Ver Mensaje
Al utilizar new, ¿Simplemente se reserva más espacio en la memoria sin afectar a los datos que hay en ella?, es decir, ¿Todos los datos que hay en "cad" siguen intactos con la diferencía que ahora tengo más espació en los arrays verdad?, ¿como un "realloc"?.

Otra cosa, delete [], lo que hace es eliminar la reserva de espació en la memoria y new genera nueva reserva de espació en la memoria dinamica... ¿Todo sin afectar a los datos que había en esos espacios de memoria verdad?.

Simplemente tengo esa duda al ver que usaste delete, luego new y luego concatenaste a cad
No haber, el sistema de memoria es más sencillo que eso. Digamos que sería un malloc simplificado.

El operador new le pide al sistema operativo que le reserve memoria. Si la petición es aceptada, obtienes la dirreción donde se encuentra tu memoria reservada.

De modo que:

Código C++:
Ver original
  1. char* Ejemplo; // puntero
  2.  
  3. Ejemplo = new char[10]; //Pido al sistema operativo 10 bytes
  4.  
  5. Ejemplo = new char[15]; // Vuelvo a pedirle el sistema operativo 15 bytes, obtengo otra dirreción diferente

Esto es un error grave, puesto que ahora mismo tenemos reservada 25 bytes de memoria pero solo tenemos la dirreción de los ultimos 15 bytes, los otros 10 bytes son "memoria perdida" (al sistema operativo le consta como reservada pero como no tenemos su dirreción no podemos usarla).

Si además tenemos datos importantes en esos 10 bytes, también los perderemos (new no maneja los datos, simplemente pide memoria al SO y te devuelve su dirreción).

Por eso en el código, he usado primero delete[] para liberar la memoria anterior y despues he hecho una nueva petición... Aunque ahora que me doy cuenta, se me ha olvidado guardar los datos antes (en una cadena auxiliar por ejemplo).



La verdad esque si voy a redimensionar en tiempo de ejecución. No usaría el delete/new sino la clase vector. Su sintaxis es:

Código C++:
Ver original
  1. vector<tipo> nombre; // Declaración del vector
  2. nombre.push_back(elemento); // Añadir un elemento al vector

Ejemplo:

Código C++:
Ver original
  1. #include <vector>
  2.  
  3. //...
  4.  
  5. vector<int> Numeros; // Vector de enteros
  6. int Buffer;
  7. cout<<"Introduzca elementos hasta que encuentre el cero";
  8.  
  9. do
  10. {
  11.   cin>> Buffer;
  12.   nombre.push_back(Buffer); // añado el numero al vector
  13. } while (Buffer != 0);
  14.  
  15. // Los muestro por pantalla
  16.  
  17. for (int i = 0; i < Numeros.size();i++) // Numeros.size() devuelve el tamaño del vector
  18.    cout<<Numeros[i];
  19.  
  20. Numeros.resize(5); // Modificamos el tamaño del vector, si el vector es más pequeño que cinco se añadirán elementos nulos, en caso contrario se suprimirán los ultimos elementos.
  21.  
  22. vector<int> Cosa;
  23. Cosa = Numeros; // operador = sobrecargado
  24.  
  25. Cosa.pop_back(); // Eliminando el ultimo elemento
  26.  
  27. if (Numeros > Cosa) // Operador > sobrecargado
  28.   cout<<"Hecho";

Para más información:
http://www.cplusplus.com/reference/vector/vector/

Última edición por amchacon; 28/05/2013 a las 05:52

Etiquetas: desbordamiento, ejecucion, fallo, operadores, sobrecarga
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 12:13.