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

Doble sobrecarga de operadores en C++

Estas en el tema de Doble sobrecarga de operadores en C++ en el foro de C/C++ en Foros del Web. Si, otra vez pregunto yo. Bueno. Tengo un pequeño problema. tengo una clase X. Y en esa clase tengo sobrecargado el operador de indexacion "[" ...
  #1 (permalink)  
Antiguo 08/07/2007, 12:57
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Doble sobrecarga de operadores en C++

Si, otra vez pregunto yo.
Bueno.
Tengo un pequeño problema.

tengo una clase X.
Y en esa clase tengo sobrecargado el operador de indexacion "[" y "]".
para poder hacer algo asi:

variable=objetoX[123];

Ahora, al sobrecargar el operador =, como puedo hacer para que esto funcione:
objetoX[123]=valorY;

Es posible hacerlo.

Saludos
  #2 (permalink)  
Antiguo 09/07/2007, 07:54
Avatar de _Lucifer_  
Fecha de Ingreso: junio-2006
Mensajes: 1.662
Antigüedad: 18 años, 5 meses
Puntos: 28
Re: Doble sobrecarga de operadores en C++

Tienes que sobecargarlo para que retorne una referencia al objeto que quieres modificar, en "Thinking in C++" está MUY bien explicado todo eso, no me acuerdo en cual de los dos volúmenes.

Saludos
__________________
Si crees que no tiene sentido, etonces probablemente lo tenga... :arriba:
  #3 (permalink)  
Antiguo 09/07/2007, 09:10
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Re: Doble sobrecarga de operadores en C++

Cita:
Iniciado por _Lucifer_ Ver Mensaje
Tienes que sobecargarlo para que retorne una referencia al objeto que quieres modificar, en "Thinking in C++" está MUY bien explicado todo eso, no me acuerdo en cual de los dos volúmenes.

Saludos
Ya habia visto que se puede hacer con referencias, de hecho en el tutorial de C con clases viene tambien muy bien explicado, pero lo que no quiero es eso, referencias. Quiero que sea por valor.
De todos modos si no se puede podre resolverlo de otra manera.

Saludos
  #4 (permalink)  
Antiguo 09/07/2007, 10:54
Avatar de _Lucifer_  
Fecha de Ingreso: junio-2006
Mensajes: 1.662
Antigüedad: 18 años, 5 meses
Puntos: 28
Re: Doble sobrecarga de operadores en C++

Solo por curiosidad...¿por qué no quieres usar referencias?

Saludos
__________________
Si crees que no tiene sentido, etonces probablemente lo tenga... :arriba:
  #5 (permalink)  
Antiguo 09/07/2007, 19:03
 
Fecha de Ingreso: febrero-2003
Ubicación: D.F.
Mensajes: 163
Antigüedad: 21 años, 9 meses
Puntos: 22
Re: Doble sobrecarga de operadores en C++

Cita:
Ya habia visto que se puede hacer con referencias, de hecho en el tutorial de C con clases viene tambien muy bien explicado, pero lo que no quiero es eso, referencias. Quiero que sea por valor.
Pues puedes hacerlo sin retornar la referencia al objeto aunque perderias algunos casos, y como no has especificado si "objetoX[123]" es tambien un objeto de la clase X supondré que si.

Entonces pudieras tener algo del estilo:

Código:
ClaseX ClaseX::operator=(tipoY y)
{
       //asignaciones aquí...
       return *this;
}
Y es claramente valido para:
Código:
objetoX[123] = valorY;
/*** que viene siendo ***/
// objetoX[123].operator=(valorY);
Pero por ejemplo, aunque la siguiente expresión es válida, no lo será para nuestra definición del operador "=":
Código:
(objetoX[123] = valorY) = valorZ;
/*** que viene siendo ***/
// (objetoX[123].operator=(valorY)).operator=(valorZ);
Aquí tenemos el caso en donde un objeto retornado por la funcion operator=()
es usado para llamar una vez mas a la función operator=(), y si solo estamos retornando el objeto ClaseX esta mal porque estamos retornando una copia temporal del objeto original y no se permite invocar funciones miembro desde objetos temporales, es por esto que es necesario no solo retornar una copia del objeto modificado sino una referencia para abarcar los casos a detalle cuando sobrecargamos el operador de asignación. En otras palabras el valor de retorno cuando el tipo de retorno es solo ClaseX no es un lvalue.

En fin es solo eso, para abarcar todos los posibles casos y darle un soporte de uso normal al operador de asignacion dentro de C++, mas no es obligatorio retornar la referencia.

Saludos Instru.
  #6 (permalink)  
Antiguo 09/07/2007, 22:13
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Re: Doble sobrecarga de operadores en C++

Cita:
Iniciado por fightmx Ver Mensaje
Pues puedes hacerlo sin retornar la referencia al objeto aunque perderias algunos casos, y como no has especificado si "objetoX[123]" es tambien un objeto de la clase X supondré que si.

Entonces pudieras tener algo del estilo:

Código:
ClaseX ClaseX::operator=(tipoY y)
{
       //asignaciones aquí...
       return *this;
}
Y es claramente valido para:
Código:
objetoX[123] = valorY;
/*** que viene siendo ***/
// objetoX[123].operator=(valorY);
Pero por ejemplo, aunque la siguiente expresión es válida, no lo será para nuestra definición del operador "=":
Código:
(objetoX[123] = valorY) = valorZ;
/*** que viene siendo ***/
// (objetoX[123].operator=(valorY)).operator=(valorZ);
Aquí tenemos el caso en donde un objeto retornado por la funcion operator=()
es usado para llamar una vez mas a la función operator=(), y si solo estamos retornando el objeto ClaseX esta mal porque estamos retornando una copia temporal del objeto original y no se permite invocar funciones miembro desde objetos temporales, es por esto que es necesario no solo retornar una copia del objeto modificado sino una referencia para abarcar los casos a detalle cuando sobrecargamos el operador de asignación. En otras palabras el valor de retorno cuando el tipo de retorno es solo ClaseX no es un lvalue.

En fin es solo eso, para abarcar todos los posibles casos y darle un soporte de uso normal al operador de asignacion dentro de C++, mas no es obligatorio retornar la referencia.

Saludos Instru.
Muchisimas gracias por tu informanio, solo que si me quedo una duda:

Cita:
ClaseX ClaseX::operator=(tipoY y)
{
//asignaciones aquí...
return *this;
}
El objetoX no es un array de objetosX, en realidad es solo un objeto con el operador de indexacion sobrecargado. Dentro de la clase del objeto hay un array, al cual quiero accesar de esta manera, como un array. Entonces, al devolver el puntero this estas devolviendo un elemento de un array de objetosX lo cual no es.
No se si me explico.

Tengo el operador de indexacion sobrecargado para poder hacer esto:

indice=cualquier_numero;
variable=objeto[indice];

Ahora quiero que tambien se pueda hacer al revez:

objeto[indice]=valor;

Donde valor es una variable de tipo byte(unsigned char) y va a ser copiada a una localidad de un arreglo interno dentro de la clase.
Es decir, como si el arreglo estuviera afuera, pero con la clase tener el control de los datos de entrada y de salida.

_Lucifer_, espero que con esto hayas visto porque las referencias no me sirven.

Saludos
  #7 (permalink)  
Antiguo 10/07/2007, 17:28
 
Fecha de Ingreso: febrero-2003
Ubicación: D.F.
Mensajes: 163
Antigüedad: 21 años, 9 meses
Puntos: 22
Re: Doble sobrecarga de operadores en C++

Cita:
El objetoX no es un array de objetosX, en realidad es solo un objeto con el operador de indexacion sobrecargado. Dentro de la clase del objeto hay un array, al cual quiero accesar de esta manera, como un array. Entonces, al devolver el puntero this estas devolviendo un elemento de un array de objetosX lo cual no es.
No se si me explico.
Parece que entendí.

Pues por lo que veo parte del problema lo causa el no poder sobrecargar el operador de asignación mas que solo a través de una clase, y dado que ClaseX[123] no es un objeto de alguna clase que hayamos definido pues simplemente no estamos en condiciones de hacerlo (creo), a menos claro, que ClaseX[123] sea de algun tipo que definamos a partir de una nueva clase y que esta a su vez almacene un miembro con el tipo de dato requerido, digamos un miembro unsigned char como lo planteaste.

El siguiente es un ejemplo muy simple de lo que trate de decir , el punto clave rádica en el uso del operador de conversión el cual sirve para poder hacer un casting de nuestro objeto a algún tipo built-in, en fin puedes buscar info a traves de "conversion operators", espero te sirva.
Código:
#include <iostream>

using std::cout;
using std::endl;
typedef unsigned char u_char;

class CUnsignedChar
{
      public:
             CUnsignedChar():c('*'){};
             CUnsignedChar& operator =(const u_char m);
             operator u_char() /** conversion operator **/
             {
                return c;
             }
      private:
               u_char c;
};

CUnsignedChar& CUnsignedChar::operator =(const u_char m)
{
    c = m;
    return *this;
}

class CArrayTest
{
      public:
             CUnsignedChar& operator [](unsigned int i);
      private:
             CUnsignedChar array[256];
};

CUnsignedChar& CArrayTest::operator [](unsigned int i)
{
    return array[i];
}

int main()
{
    CArrayTest myArray;
    u_char variable;
    int i;
    char *p = NULL;
    
    char message[] = "Mensaje de prueba... ";
    p = message;
    /*** Asignacion tipo claseX[123] = variable ***/
    while (*p)
    {
          myArray[p - message] = *p;
          p++;
    }  
    /*** Asignacion tipo variable = claseX[123]  ***/
    for (i = 0; i < 256; i++)
    {
        variable = myArray[i];
        cout << variable; /** mostrar dato **/
    }
    getchar();
    return 0;   
}
Un saludo.
  #8 (permalink)  
Antiguo 10/07/2007, 19:08
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Re: Doble sobrecarga de operadores en C++

Cita:
Iniciado por fightmx Ver Mensaje
Parece que entendí.

Pues por lo que veo parte del problema lo causa el no poder sobrecargar el operador de asignación mas que solo a través de una clase, y dado que ClaseX[123] no es un objeto de alguna clase que hayamos definido pues simplemente no estamos en condiciones de hacerlo (creo), a menos claro, que ClaseX[123] sea de algun tipo que definamos a partir de una nueva clase y que esta a su vez almacene un miembro con el tipo de dato requerido, digamos un miembro unsigned char como lo planteaste.

El siguiente es un ejemplo muy simple de lo que trate de decir , el punto clave rádica en el uso del operador de conversión el cual sirve para poder hacer un casting de nuestro objeto a algún tipo built-in, en fin puedes buscar info a traves de "conversion operators", espero te sirva.
Código:
#include <iostream>

using std::cout;
using std::endl;
typedef unsigned char u_char;

class CUnsignedChar
{
      public:
             CUnsignedChar():c('*'){};
             CUnsignedChar& operator =(const u_char m);
             operator u_char() /** conversion operator **/
             {
                return c;
             }
      private:
               u_char c;
};

CUnsignedChar& CUnsignedChar::operator =(const u_char m)
{
    c = m;
    return *this;
}

class CArrayTest
{
      public:
             CUnsignedChar& operator [](unsigned int i);
      private:
             CUnsignedChar array[256];
};

CUnsignedChar& CArrayTest::operator [](unsigned int i)
{
    return array[i];
}

int main()
{
    CArrayTest myArray;
    u_char variable;
    int i;
    char *p = NULL;
    
    char message[] = "Mensaje de prueba... ";
    p = message;
    /*** Asignacion tipo claseX[123] = variable ***/
    while (*p)
    {
          myArray[p - message] = *p;
          p++;
    }  
    /*** Asignacion tipo variable = claseX[123]  ***/
    for (i = 0; i < 256; i++)
    {
        variable = myArray[i];
        cout << variable; /** mostrar dato **/
    }
    getchar();
    return 0;   
}
Un saludo.
Wow!. Si, asi. yo no sabía que se podian sobrecargar los castings.
Pero si, asi es como lo necesito.

Muchisimas Gracias.

Saludos
  #9 (permalink)  
Antiguo 11/07/2007, 16:45
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Re: Doble sobrecarga de operadores en C++

Otra vez.

Una pregunta mas.

Tomando como referencia tu ejemplo, si en la clase cArrayTest
fuera asi:
Cita:
class CArrayTest
{
public:
CArrayTest(): numero(0){};
setNumber(unsigned char number){numero=number;};
CUnsignedChar& operator [](unsigned int i);
private:
unsigned int numero;
CUnsignedChar array[16][256];
};
pero con el operador asi:

Cita:
CUnsignedChar& CArrayTest::operator [](unsigned int i)
{
return array[numero][i];
}
No tendria algun comportamiento extraño la siguiente expresion?

Cita:

CArrayTest temp;

temp[5]=10
temp.setNumber(5);
temp[5]=10
o la siguiente?

Cita:

CArrayTest *temp;
int variable;

variable=(*temp[0])|((*temp[1])<<8);
Creo que esta claro lo que busco con ese codigo no?


Saludos

Última edición por Instru; 11/07/2007 a las 20:46
  #10 (permalink)  
Antiguo 12/07/2007, 00:34
 
Fecha de Ingreso: febrero-2003
Ubicación: D.F.
Mensajes: 163
Antigüedad: 21 años, 9 meses
Puntos: 22
Re: Doble sobrecarga de operadores en C++

Cita:
Tomando como referencia tu ejemplo, si en la clase cArrayTest
fuera asi:
Código:
 
class CArrayTest
{
public:
CArrayTest(): numero(0){};
setNumber(unsigned char number){numero=number;};
CUnsignedChar& operator [](unsigned int i);
private:
unsigned int numero;
CUnsignedChar array[16][256];
};
Solo como detalle:
Código:
class CArrayTest
{
public:
CArrayTest(): numero(0){};
void setNumber(unsigned int number){numero=number;} // <--
CUnsignedChar& operator [](unsigned int i);
private:
unsigned int numero;
CUnsignedChar array[16][256];
};
Cita:
No tendria algun comportamiento extraño la siguiente expresion?

CArrayTest temp;

temp[5]=10
temp.setNumber(5);
temp[5]=10
En realidad no, puesto que temp[5] en ambos casos sigue siendo un objeto
CUnsignedChar, lo único que se ha hecho es que ahora dispones de 4096 objetos de ese tipo y te vales de dos índices para accesarlos, uno que se establece a través de la función setNumber y el otro con la sobrecarga del operador de indexación. Lo anterior es lo mismo que:
Código:
temp[5]=10;
temp.setNumber(5);
temp[1285]=10;  // es lo mismo que temp[256*5 + 5] = array[5][5]
Cita:
o la siguiente?

CArrayTest *temp;
int variable;

variable=(*temp[0])|((*temp[1])<<8);
No me queda muy claro, para este caso declaras el puntero *temp pero no apunta a nada (tal vez sea por cuestión de ejemplo supongo). Pero entonces para usarlo podria ser algo asip:
Código:
    CArrayTest *temp = new CArrayTest;
    (*temp)[0] = 0;
    (*temp)[1] = 1;
    cout << ((*temp)[0] | ((*temp)[1] << 8)) << endl; // 256 
    temp->setNumber(16);
    /** accesando al último elemento... **/
    cout << ((*temp)[255] == (*temp)[4095]) << endl; // 1 
    delete temp;
Cita:
Creo que esta claro lo que busco con ese codigo no?
No se si te refieres a la última línea que pusiste de código?
Salu2
  #11 (permalink)  
Antiguo 12/07/2007, 10:50
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Re: Doble sobrecarga de operadores en C++

Cita:
No me queda muy claro, para este caso declaras el puntero *temp pero no apunta a nada (tal vez sea por cuestión de ejemplo supongo). Pero entonces para usarlo podria ser algo asip:
Lo siento, pero si fue un ejemplo que me hice aqui mismo sin revisar mucho.

Entonces me surge otra duda.

Si tengo

CArrayTest *temp=new CArrayTemp;

al usar

(*temp)[60]=algo;

es lo mismo que si no usara puntero y fuera asi?

temp[60]=algo;

Tambien,

Que no se supone que al usar:

(*temp)[4095]=valor;

seria un sebordamiento, claro, siempre y cuando la memoria no haya sido apartada linealmente?

Saludos
  #12 (permalink)  
Antiguo 12/07/2007, 12:14
 
Fecha de Ingreso: febrero-2003
Ubicación: D.F.
Mensajes: 163
Antigüedad: 21 años, 9 meses
Puntos: 22
Re: Doble sobrecarga de operadores en C++

Cita:
al usar

(*temp)[60]=algo;

es lo mismo que si no usara puntero y fuera asi?

temp[60]=algo;
Pues practicamente sip.

Cita:
Que no se supone que al usar:

(*temp)[4095]=valor;

seria un sebordamiento, claro, siempre y cuando la memoria no haya sido apartada linealmente?
Sip, tienes razón, esta mal ese código que puse en la última parte, algo correcto podria ser asip:
Código:
    CArrayTest *temp = new CArrayTest;
    (*temp)[0] = 0;
    (*temp)[1] = 1;
    cout << ((*temp)[0] | ((*temp)[1] << 8)) << endl;
    (*temp)[4095] = 'F'; /** último elemento **/
    temp->setNumber(15);
    /** accesando al último elemento... **/
    cout << ((*temp)[255]) << endl; 
    delete temp;
Solo trataba de mostrar el acceso al arreglo linealmente(cuando el primer índice es cero) o a través de setNumber, pero solo eso.
  #13 (permalink)  
Antiguo 12/07/2007, 15:55
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 22 años
Puntos: 52
Re: Doble sobrecarga de operadores en C++

Pues muchisimas gracias.
Todo esto me sirvio muchisimo.

Saludos
  #14 (permalink)  
Antiguo 12/07/2007, 20:24
 
Fecha de Ingreso: febrero-2003
Ubicación: D.F.
Mensajes: 163
Antigüedad: 21 años, 9 meses
Puntos: 22
Re: Doble sobrecarga de operadores en C++

Por nada. Un Saludo.
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 13:45.