2012-01-14 36 views
5

tengo una clase llamada Location y tenía que añadir un CArray a sus variables miembro. Este cambio provocó la necesidad de sobrecargar el operador de asignación.C++ sobrecarga operador de asignación

¿Hay alguna manera de copiar todas las variables en este tipo de clase que se estaban copiando antes de realizar el cambio y simplemente agregar el código adicional para copiar CArray sin copiar cada variable de miembro individualmente?

Location& Location::operator=(const Location &rhs) 
{ 
    // Only do assignment if RHS is a different object from this. 
    if (this != &rhs) 
    { 
     //Copy CArray 
     m_LocationsToSkip.Copy(rhs.m_LocationsToSkip); 

     //Copy rest of member variables 
     //I'd prefer not to do the following 
     var1 = rhs.var1; 
     var2 = rhs.var2; 
     //etc 
    } 

    return *this; 
} 
+0

Así que usted quiere, en efecto, llamar al operador de asignación generado por el compilador? ¿'CArray' tiene un operador de asignación? –

+0

Tiene un constructor de copia pero no un operador de asignación. No estoy seguro de poder llamar al operador de asignación generado por el compilador ya que agregué una variable miembro de CArray. –

+2

No, no puede llamar al compilador generado porque ya no se genera cuando proporciona uno (no porque haya agregado un miembro CArray; lo único que cambia es que el compilador generado para su clase no puede llamar al uno para CArray porque no existe). Me temo que no hay forma de hacer esto. –

Respuesta

4

Sí, algo así. Use un tipo que sobrecarga operator=, por lo que no tiene que hacerlo en la clase contenedora. Incluso cuando escribo código MFC, todavía uso principalmente std::vector, std::string, etc., en lugar de la colección MFC y las clases de cadenas. A veces estás bastante atrapado usando CString, pero no recuerdo la última vez que usé CArray en lugar de std::vector.

+0

Creo que este es el más cercano a lo que necesito. Lamentablemente, el resto de la aplicación usa contenedores mfc y odio cambiar esto para usar un contenedor STL. Sin embargo, esta es una buena solución. Gracias. –

0

No, usted no puede. La mejor forma de hacerlo es usar script para generar código real.

0

Esto se hace generalmente con lo que se conoce como "copia y cambio de idioma". Implementa un constructor de copia y un método swap() que intercambia valores de miembros y, lo que es más importante, punteros a datos externos. Con eso su operador de asignación se ve así:

C& C::operator=(const C& c) { 
    C tmp(c); 
    this->swap(tmp); 
    return *this; 
} 

Ni siquiera necesita un protector de asignación automática con esto.

+0

Pero ahora tiene que enumerar todos los miembros en su implementación 'swap'. Esto solo mueve el problema, no lo resuelve. –

+0

Bueno, no veo un problema aquí. Demasiados miembros de valor? Empaquetarlos en una estructura y simplemente hacer una tarea si va a menos tipeo. –

2

Sí. Lo que suelo hacer es poner todo en una estructura de miembros en la clase, excepto lo que no se puede copiar. De esta manera:

class Location 
{ 
    struct Members 
    { 
     int var1, var2; 
    }; 

    Members m; 
    CArray m_LocationsToSkip; 

public: 
    Location& operator=(Location const& rhs); 
}; 

Location& Location::operator=(const Location &rhs) 
{ 
    // Only do assignment if RHS is a different object from this. 
    if (this != &rhs) 
    { 
     //Copy CArray 
     m_LocationsToSkip.Copy(rhs.m_LocationsToSkip); 

     //Copy rest of member variables 
     m = rhs.m; //will use Members automatically generated operator= 
        //which should do the correct thing because you only put 
        //normally copyable members in m 
    } 

    return *this; 
} 

que por primera vez sobre esto aquí: https://stackoverflow.com/questions/469696/what-is-your-most-useful-c-c-utility/1609496#1609496

+0

Esto parece una solución decente, pero se necesitaría bastante refactorización en el resto de la aplicación para respaldar esto. –

+0

@Cole W: ¿cómo es eso? ¿sus miembros son públicos y se usan en todas partes en la aplicación? En ese caso, otra alternativa sería crear una clase de gestión de recursos para englobar el CArray (algo al revés que en el ejemplo), por lo que posiblemente solo tenga un miembro que pueda necesitar refactorización (posiblemente no dependiendo de cómo se use)) Utilicé ese ejemplo con la estructura porque eso es lo que necesitaba en mi código (era para puntero, no para una matriz, y un puntero inteligente no era lo que necesitaba) pero en su caso, la creación de una clase de administración de recursos para la CArray podría ser una mejor opción. – n1ckp