elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Sobrecarga de operador
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] 2 Ir Abajo Respuesta Imprimir
Autor Tema: Sobrecarga de operador  (Leído 5,432 veces)
digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Sobrecarga de operador
« en: 15 Mayo 2019, 15:54 pm »

Hola amigos..

Estoy experimentando con el contenedor set y tengo duda con el operador de sobrecarga que se necesita para meter al contenedor un tipo creado por mi mismo...

Según estuve leyendo y alguien me dijo también que necesito sobrecargar el operador <

Pero este operador menor que, en que forma hace la comparación de elementos?, el contenedor set no permite objetos duplicados, no seria mas lógico sobrecargar == en vez de < para comparar si el elemento ya existe?




En línea

Dungeons & dragons;
dragons.Attack();
CalgaryCorpus


Desconectado Desconectado

Mensajes: 323


Ver Perfil WWW
Re: Sobrecarga de operador
« Respuesta #1 en: 15 Mayo 2019, 16:15 pm »

Sobrecarga <<
No <


En línea

Aqui mi perfil en LinkedIn, invitame un cafe aqui
@XSStringManolo
Hacker/Programador
Colaborador
***
Desconectado Desconectado

Mensajes: 2.399


Turn off the red ligth


Ver Perfil WWW
Re: Sobrecarga de operador
« Respuesta #2 en: 15 Mayo 2019, 18:42 pm »

https://en.cppreference.com/w/cpp/language/operators
Aqui tienes todos los operadores explicados y con ejemplos.

Para comparar contenedores del mismo tipo y longitud se sobrecarga el operador == los elementos dentro de los contenedores del mismo tipo tambien deben ser elementos del mismo tipo.

La sobrecarga del operador << es para imprimir en pantalla los elementos del set.
En línea

Mi perfil de patrocinadores de GitHub está activo! Puedes patrocinarme para apoyar mi trabajo de código abierto 💖

K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Sobrecarga de operador
« Respuesta #3 en: 15 Mayo 2019, 19:42 pm »

Hola amigos..

Estoy experimentando con el contenedor set y tengo duda con el operador de sobrecarga que se necesita para meter al contenedor un tipo creado por mi mismo...

Según estuve leyendo y alguien me dijo también que necesito sobrecargar el operador <

Pero este operador menor que, en que forma hace la comparación de elementos?, el contenedor set no permite objetos duplicados, no seria mas lógico sobrecargar == en vez de < para comparar si el elemento ya existe?

Creo que a lo que te refieres es al tipo de ordenación interno del <set>. Un <set> es un conjunto de valores no repetidos y ordenados según un criterio que puedes elegir tú (criterio por defecto: less<T>). Es por esto que si creas un <set> para almacenar objetos deben poder ordenarse de menor a mayor y para ello tienes dos opciones:
  • Sobrecargar el operador <.
  • Crear un functor. (Verás que se hablan mucho de functores para <set> y <priority_queue>.
Código
  1. // OPCION 1: Sobrecarga de <
  2. struct foo{
  3.    // miembros
  4.    bool operator<(const foo &f)const{/*...*/}
  5. };
  6. std::set<foo> my_set; // equivalente a std::set<foo, less<foo>, allocator<foo>> se necesita el operador para el criterio less<foo>
  7.  
  8. // OPCION 2: Functor
  9. struct foo{
  10.    // miembros
  11. };
  12.  
  13. struct comparaFoo{
  14.    bool operator()(const foo &f1, const foo &f2)const{/*...*/}
  15. };
  16. std::set<foo, comparaFoo> my_set; // cambiamos el criterio por defecto por el nuestro

Si quieres saber más sobre esto: http://www.cplusplus.com/reference/set/set/
Puedes leer la teoría. Es muy concisa pero precisa, creo que está muy bien para entenderlo (aunque en inglés, pero es un inglés sencillo). Suerte :-X
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
Loretz

Desconectado Desconectado

Mensajes: 117


Ver Perfil
Re: Sobrecarga de operador
« Respuesta #4 en: 15 Mayo 2019, 20:12 pm »

Sí, así es. Necesitas sobrecargar el "operator<"; también puedes usar una función objeto (function object) que defina cuando uno de esos tipos es "menor que" el otro, y también puedes crear el set usando una expresión lambda como función de comparación. Las tres son funcionalmente equivalentes.

Un std::set contiene un conjunto ordenado de claves únicas, es por eso que necesitas una función que sirva para las dos cosas, definir el orden y garantizar unicidad. El operator< define un "strict weak ordering" (googlear) que es lo que necesita un std::set para establecer orden y unicidad, que se obtiene a partir de la relación de equivalencia (que no la igualdad), obtenida a partir del mismo operator<.
En línea

digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Re: Sobrecarga de operador
« Respuesta #5 en: 16 Mayo 2019, 18:15 pm »

Gracias por las respuestas...

Muy bien, creo que tomare todas las opciones, tanto para comparar como para imprimir la clase y determinar el orden...

< , << y ==

Y gracias también por los enlaces..
En línea

Dungeons & dragons;
dragons.Attack();
digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Re: Sobrecarga de operador
« Respuesta #6 en: 17 Mayo 2019, 04:20 am »

Rayos cósmicos... he intentado sobrecargar al menos el operador < .. pero algo no anda bien..  esta vez compila, pero no se comporta como esperaba

Código
  1.  
  2. #include "pch.h"
  3. #include <iostream>
  4. #include <set>
  5.  
  6. class Usuario {
  7.  
  8. char * nombre = nullptr;
  9.  
  10.  
  11. public:
  12. Usuario() : nombre(new char[16]) {}
  13. ~Usuario();
  14.  
  15. void SetNombre(const char * _nombre);
  16.  
  17.  
  18. char * GetNombre() const {
  19. return this->nombre;
  20. }
  21.  
  22. friend bool operator<(const Usuario & _thisUser, const Usuario & _otherUser);
  23.  
  24.  
  25. };
  26.  
  27. Usuario::~Usuario() {
  28. delete[] nombre;
  29. }
  30.  
  31. void Usuario::SetNombre(const char * _nombre) {
  32. strcpy(this->nombre, _nombre);
  33. }
  34.  
  35. bool operator<(const Usuario & _thisUser, const Usuario & _otherUser) {
  36.  
  37. for (int l = 0; l < 16; l++) {
  38. if (_thisUser.nombre[l] < _otherUser.nombre[l]) {
  39. return true;
  40. }
  41. else {
  42.  
  43. if (_thisUser.nombre[l] == _otherUser.nombre[l])
  44. continue;
  45.  
  46. else
  47. return false;
  48.  
  49. }
  50. }
  51.  
  52.  
  53. }
  54.  
  55.  
  56.  
  57. std::set<Usuario> usuarios;
  58.  
  59. int main(){
  60.  
  61. char * _nombre = new char[16];
  62.  
  63. for (int x = 0; x <= 3; x++) {
  64.  
  65. system("cls");
  66.  
  67. std::cout << "Ingrese nombre: ";
  68. std::cin >> _nombre;
  69.  
  70. std::cout << std::endl;
  71.  
  72. Usuario usuario;
  73. usuario.SetNombre(_nombre);
  74.  
  75. usuarios.insert(usuario);   //ciclo 0 lo realiza bien
  76.                                                      //al intentar guardar en el ciclo 1 se congela
  77.  
  78. }
  79.  
  80. delete[] _nombre;
  81. _nombre = nullptr;
  82.  
  83. return 0;
  84.  
  85. }
  86.  

He optado por set<> porque deseo ingresar usuarios y no deben repetirse...
Estoy casi seguro que no he sobrecargado correctamente el operador..
« Última modificación: 17 Mayo 2019, 04:24 am por digimikeh » En línea

Dungeons & dragons;
dragons.Attack();
K-YreX
Moderador
***
Desconectado Desconectado

Mensajes: 1.008



Ver Perfil
Re: Sobrecarga de operador
« Respuesta #7 en: 17 Mayo 2019, 04:46 am »

Bueno el problema principal como bien dices es que el operador < no está bien sobrecargado. Este operador pertenece a la clase, no es un operador externo a la clase que deba declararse como <friend>, es decir, sería así:
Código
  1. bool Usuario::operator<(const Usuario &otro)const{
  2.    return strncmp(this->nombre, otro.nombre, size) < 0;
  3. }
Esa función compara el número de caracteres indicados en <size> de ambas cadenas y retorna un valor negativo si la primera es menor a la segunda, un valor positivo si la primera es mayor a la segunda y 0 si son iguales.

Además de eso la declaración de <usuario> la puedes hacer una única vez antes de empezar el bucle y luego ir cambiando el valor de <nombre> en cada iteración.

Además no tiene mucho sentido usar arrays dinámicos si siempre los creas de tamaño 16, porque entonces... hasta dónde comparas las cadenas?? Tienes dos opciones:
  • Crear un array estático muy grande donde guardar el nombre introducido por el usuario, calcular los caracteres útiles y entonces reservar memoria justo para esos caracteres.
  • Usar string que es la ventaja de C++ para trabajar con cadenas de caracteres. Si usas string tendrás que convertirlos a char* para usar las funciones típicas de las cadenas pero eso se puede hacer simplemente con <nombre_string.c_str()>

Aparte de eso, el <set> mejor que sea local en el <main> en lugar de global.
En línea

Código
  1. cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
Loretz

Desconectado Desconectado

Mensajes: 117


Ver Perfil
Re: Sobrecarga de operador
« Respuesta #8 en: 17 Mayo 2019, 08:50 am »

Primero voy a hacer algunos comentarios morales:

Estás aprendiendo C++, entonces:

0) necesitas un buen libro.

1) no uses new (y no uses delete). Son mecanismos para situaciones excepcionales. En la vida real, cuando un experto los usa, debe dar explicaciones, convincentes.

2) no uses system(), menos en algo como system("cls"); Si estás intentando aprender el lenguaje, ¿cómo es que ya has aprendido los vicios de un mal programador de hace 30 años?

3) no uses std::endl;  no lo necesitas. Quizá, si en algún momento te encuentras en las fronteras de alguna sofisticada arquitectura concurrente, bueno, en ese momento supongo que ya sabrás. Mientras tanto sólo molesta.

4) no uses strcpy(), estás llamando a la desgracia. Pero de todos modos, así como en C++ no se usan punteros tampoco se usan arrays, así que obviamente strcpy no tiene ninguna razón de ser.

Y un comentario técnico:

Tu programa tiene dos errores:

1) La función de comparación (tu operator<()) no tiene en cuenta cuando las dos cadenas son iguales. Puedes probar con:
Código:
bool operator<(const Usuario& _thisUser, const Usuario& _otherUser) {
    return strcmp(_thisUser.nombre, _otherUser.nombre) < 0;
}



2) estás usando delete dos veces sobre el mismo puntero.

En esta porción del
Código
  1.        Usuario usuario;  ///< creas un Usuario
  2.        // etcetera,,,
  3.        usuarios.insert(usuario);   ///< insertas una copia de tu Usuario en el set.
  4.  

El problema es que usuarios.insert() inserta una copia, y como no has definido qué es hacer una copia de un Usuario, el compilador ha sintetizado tanto el "copy constructor" como el "copy assignment operator", y en ese caso hace una "shallow copy" del puntero nombre.

Luego se está invocando delete[] dos veces sobre cada uno de los punteros. La primera vez cuando la variable local usuario sale de ámbito y la segunda vez cuando el set usuarios sale de ámbito (se invoca el destructor de sus elementos).
Puedes reemplazar tu destructor por este otro para ver que se está invocando dos veces delete[] para cada nombre:
Código:
Usuario::~Usuario() {
    std::cout << "delete[] " << nombre << '\n';
    //delete[] nombre;
}

Lectura:
https://en.cppreference.com/w/cpp/language/rule_of_three The rule of three/five/zero



En línea

digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Re: Sobrecarga de operador
« Respuesta #9 en: 18 Mayo 2019, 02:21 am »

Gracias por las respuestas..

me queda claro todo, lo único si que no comprendí bien el por qué de dos cosas

por qué dices que no debo usar system("cls"); de que otra forma puedo limpiar pantalla?..  (conozco otro método que es insertar 100 lineas vacías pero esto haría que el contenido se muestre abajo)

y lo otro, es el std::endl;  la otra forma que conozco es con la secuencia de escape \n

Saludos!
En línea

Dungeons & dragons;
dragons.Attack();
Páginas: [1] 2 Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
sobrecarga de operador<<
Programación C/C++
adam96 5 4,541 Último mensaje 17 Diciembre 2010, 19:10 pm
por Littlehorse
Sobrecarga operador +
Programación C/C++
_Enko 4 2,625 Último mensaje 6 Febrero 2015, 14:56 pm
por _Enko
Sobrecarga operador -> [C++]
Programación C/C++
K-YreX 2 1,748 Último mensaje 6 Enero 2019, 17:21 pm
por K-YreX
Sobrecarga de operador y constructores/destructores
Programación C/C++
digimikeh 8 2,760 Último mensaje 18 Junio 2019, 15:35 pm
por digimikeh
Sobrecarga operador+ y miembro puntero...
Programación C/C++
digimikeh 5 2,032 Último mensaje 19 Junio 2019, 05:22 am
por digimikeh
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines