2012-04-28 10 views
5

Digamos que tenemos esta clase A:¿Cómo uso una cadena de sobrecargas del operador sin modificar los operandos?

class A 
{ 
public: 
    int a; 

    A(int b) 
    { 
     a = b; 
    } 
}; 

me gustaría crear una sobrecarga + tales que podía utilizar de esta manera

A a(1),b(2),c(3),&d; 
d = a + b + c; 

sin modificar el contenido de cada objeto. La siguiente cosa lógica sería la asignación de un nuevo trozo de memoria cada momento como este:

A &operator+ (const A &b) 
{ 
    A *c = new A(a+b.a); 
    return *c; 
} 

Pero esto crearía un nuevo problema: los resultados intermedios se pierden, causando pérdidas de memoria. Pude haber resuelto fácilmente este problema haciendo una función estática que toma tres referencias de objetos A y almacena la suma de las dos primeras en el tercero, pero estoy dispuesto a apostar que debe haber alguna forma de hacer que ocurra una sobrecarga. camino que quiero

Entonces la pregunta es: ¿hay alguna manera en que yo podría usar una cadena de sobrecargas del operador que no modifique los operandos sin causar pérdidas de memoria?

Respuesta

9

puede simplemente usar paso por valor y hace esto:

A operator+ (A other) //pass by value 
{ 
    other.a += a; 
    return other; 
} 

O, puesto que el miembro a es accesible al público, puede (y no debe) hacer operator+ una función no miembro que :

A operator+(A left, A const &right) 
{ 
    left.a += right.a; 
    return left; 
} 

en cuenta que el primer argumento es aceptado por el valor , y el segundo por referencia. De esta forma, no necesita declarar una variable local en la función. Puedes usar el primer parámetro; después de todo, es local para la función, puede hacer lo que quiera con él: en este caso, simplemente le agregamos right.a y lo devuelve.


un mejor diseño de la clase sería la siguiente: (leer los comentarios) Alerta

class A 
{ 
    int a; //make it private 
public:  
    A(int b) : a(b) //use member initialization list 
    { 
    } 
    A& operator+=(A const & other) //add `+=` overload, as member of the class 
    { 
     a += other.a; 
     return *this; 
    } 
}; 

//and make `+` non-member and non-friend 
A operator+(A left, A const & right) 
{ 
    left += right; //compute this in terms of `+=` which is a member function 
    return left; 
} 
+1

+1 para evitar la copia manual. – Sven

+0

lo siento, pero su respuesta parece haber ignorado el hecho de que estaba preguntando específicamente sobre una forma de no modificar ninguno de los objetos de operando –

+0

@ user803253: No modifico los * operandos *; los operandos se pasan como valor, lo que significa que lo que modifica en la función son * copias * de los operandos. De todos modos, publiqué un mejor diseño que debes adoptar. – Nawaz

4

No hay necesidad de utilizar punteros dentro de operator+. Puede asignar el objeto intermedio en la pila y luego devolverlo:

A operator+ (const A &b) 
{ 
    A c(a+b.a); 
    return c; 
} 

O simplemente:

A operator+ (const A &b) 
{ 
    return A(a+b.a); 
} 

O aún más simple:

A operator+ (const A &b) 
{ 
    return a+b.a; 
} 

Dado que esto exige implícitamente A::A(int).

Tenga en cuenta que eliminé la referencia del tipo de devolución. No puede devolver una referencia no const a un local.

allí tendría que usarlo de esta manera:

A a(1),b(2),c(3),d; 
d = a + b + c; 

Tenga en cuenta que d ya no es una referencia.

+0

: Ustedes están regresando a las referencias temporales. ¡Esa no es una buena idea! –

+0

funciona muy bien! Gracias. Sabía que algo simple debía hacerse. –

+0

Tan pronto como publiqué mi respuesta, noté que OP devolvía referencias, pero solucioné mi respuesta de inmediato. – mfontanini

Cuestiones relacionadas