Pregunta

Estoy un poco confundido en cuanto a por qué me han dicho que devuelva const foo de un operador binario en c ++ en lugar de solo foo.

He estado leyendo "Pensamiento en C ++" de Bruce Eckel, y en el capítulo sobre sobrecarga del operador, dice que "haciendo que el valor de retorno [de un operador binario sobrecargado] const, indique que solo se puede llamar a una función miembro const para ese valor de retorno. Esto es correcto, porque le impide almacenar información potencialmente valiosa en un objeto que probablemente se perderá ".

Sin embargo, si tengo un operador más que devuelve const, y un operador de incremento de prefijo, este código no es válido:

class Integer{
int i;

public:
    Integer(int ii): i(ii){ }
    Integer(Integer&);

    const Integer operator+();
    Integer operator++();
};


int main(){

Integer a(0);
Integer b(1);

Integer c( ++(a + b));
}

Para permitir este tipo de asignación, ¿no tendría sentido que el operador + devuelva un valor no constante? Esto podría hacerse agregando const_casts, pero eso se vuelve bastante voluminoso, ¿no?

¡Gracias!

¿Fue útil?

Solución

Cuando dices ++ x, estás diciendo "suma 1 a x, almacena el resultado nuevamente en x y dime qué era". Este es el operador de preincremento. Pero, en ++ (a + b), ¿cómo se supone que debes "almacenar el resultado de nuevo en a + b"?

Ciertamente, podría almacenar el resultado nuevamente en el temporal que actualmente contiene el resultado de a + b, que desaparecería pronto. Pero si realmente no le importaba dónde se almacenaba el resultado, ¿por qué lo incrementó en lugar de simplemente agregar uno?

Otros consejos

FYI, ++ (a + b) es ilegal incluso con POD (tipos de datos antiguos simples, como int ). Por lo tanto, tiene sentido no permitirlo para sus propios tipos de clase tampoco. Prueba esto:

int a = 1;
int b = 2;
int c = ++(a+b);

GCC devuelve error : lvalue requerido como incremento de operando .

En su caso, sería preferible hacer que su constructor de copia tome un argumento const Integer y cree su Integer c de esta manera:

Integer c(a + b + Integer(1));
Los

constructores de copias generalmente toman una referencia const para resolver ese problema por usted.

(Tener un copiador no constante implica alguna transferencia de recursos, lo que puede ser útil a veces, pero para el 99% de todas las situaciones, no es necesario)

Creo que el ejemplo de OP sería adecuado para la pregunta si el operador de suma se sustituye por cualquier otro operador binario que devuelva una referencia, por ejemplo, un operador de asignación:

Integer c( ++(a = b));

Vine aquí preguntándome si debería hacer que mi operador de asignación devuelva una referencia constante o no constante. Algunos tutoriales use versiones que no sean constantes, al contrario de "Pensar en el consejo de C ++". Y algunas otras referencias dan un razonamiento detrás de eso:

  

Observe que la referencia devuelta no se declara const. Esto puede ser un poco confuso, porque te permite escribir cosas locas como esta:

     
    

MyClass a, b, c;

         

...

         

(a = b) = c; // ¿Qué ??

  
     

A primera vista, es posible que desee evitar situaciones como esta, haciendo que operator = devuelva una referencia constante. Sin embargo, declaraciones como esta funcionarán con tipos primitivos. Y, lo que es peor, algunas herramientas realmente dependen de este comportamiento. Por lo tanto, es importante devolver una referencia no constante de su operador =. La regla general es: "Si es lo suficientemente bueno para las entradas, es lo suficientemente bueno para los tipos de datos definidos por el usuario".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top