Pregunta ¿Por qué el operador de incremento postfix toma un parámetro ficticio?


Eche un vistazo a estas firmas de funciones:

 class Number {
 public:
   Number& operator++ ();    // prefix ++
   Number  operator++ (int); // postfix ++
 }; 

El prefijo no toma ningún parámetro, pero postfix sí lo hace. ¿Por qué? Pensé que podemos reconocerlos con diferentes tipos de devolución.


16
2017-08-26 11:58


origen


Respuestas:


Usted es libre de darle al operador ++ cualquier tipo de devolución que desee, por lo que no hay forma de distinguir postfijo y prefijo por eso. Entonces el compilador necesita algún tipo de pista.

OTOH, no sé por qué esto no se pudo haber hecho solo en sintaxis:

//prefix
int& ++operator (); 
//postfix
int& operator++ (); 

Después de todo, imitar el uso en declaraciones tiene tradición en C y C ++.

PD Otros carteles: esto no tiene nada que ver con la sobrecarga por tipo de devolución. postfix y el prefijo ++ / - son dos nombres diferentes. No hay necesidad de resolver una sobrecarga en x++ o ++x, porque está completamente claro qué nombre significa.


8
2017-08-26 12:00



Prefijo y postfijo ++ son diferentes operadores. Con el estándar Foo operator symbol(Foo &) declaración de estilo no había una manera obvia de distinguir los dos. En lugar de venir con una nueva sintaxis como Foo symbol operator(Foo &) lo que lo convertiría en un caso especial a diferencia de todos los demás operadores y probablemente un poco doloroso de analizar, los diseñadores de idiomas querían alguna otra solución.

La solución que eligieron fue algo extraña. Observaron que todos los demás operadores 'postfix' (es decir, operadores que ocurrieron después de uno de sus operandos) eran en realidad operadores infija que tomaban dos argumentos. Por ejemplo, simple viejo + o -. Sobre esta base, los diseñadores del lenguaje decidieron que tener un argumento ficticio aleatorio sería una buena manera de distinguir entre prefijo y postfijo ++.

En mi humilde opinión, es una de las decisiones más extrañas tomadas a medida que C ++ evolucionó. Pero ahí lo tienes.

Y no puede distinguirlos según el tipo de devolución por dos razones.

El primero es que las funciones en C ++ no se pueden sobrecargar en el tipo de retorno. No puede tener dos funciones que tengan nombres idénticos y listas de tipos de parámetros pero diferentes valores de retorno.

El segundo es que el método no sería lo suficientemente robusto o flexible como para manejar todas las posibles implementaciones de prefijo y postfijo ++.

Por ejemplo, es posible que desee un postfijo ++ que devolvió un tipo de referencia si la única razón por la que alguna vez lo llamó fue para invocar un efecto secundario no relacionado con el valor de la variable a la que lo estaba aplicando. En mi opinión, esa sería una implementación muy mala, pero C ++ no se trata de juzgar qué tipo de código estúpido quieres escribir, sino de permitirte escribir el código que consideres apropiado para la situación. Y obligarlo a usar un estilo particular de tipo de devolución para el prefijo ++ y postfix ++ sería contrario a ese espíritu.


7
2017-08-26 12:20



Directamente de la boca de Bjarne:

Esto puede ser a la vez demasiado lindo y demasiado sutil, pero funciona, no requiere una sintaxis nueva y tiene una lógica para la locura. Otros operadores unarios son prefijo y no toman argumentos cuando se definen como funciones miembro. El maniquí "extraño" y sin usar int el argumento se usa para indicar los operadores impares del sufijo. En otras palabras, en el caso de postfix, ++se encuentra entre el primer operando (real) y el segundo argumento (ficticio) y es, por lo tanto, postfijo.

Estas explicaciones son necesarias porque el mecanismo es único y por lo tanto un poco verrugoso. Si tuviera una opción, probablemente habría presentado el prefix y postfix palabras clave, pero eso no parecía factible en ese momento. Sin embargo, el único punto realmente importante es que el mecanismo funciona y puede ser entendido y utilizado por los pocos programadores que realmente lo necesitan.

Por cierto, en mi opinión, solo prefijo ++ debe ser sobrecargable por el programador, y postfix ++ debe ser generado automáticamente por el compilador. ¿Alguien esta de acuerdo conmigo?


6
2017-08-26 14:48



No está permitido sobrecargar funciones simplemente por tipo de devolución, por lo que es necesario un parámetro ficticio para diferenciar entre dos imágenes idénticas operator++() operadores.


2
2017-08-26 12:00



Si tuviera mi druthers, postincrement y muchos operadores de punto de secuencia se dividirían en dos o tres partes; en el caso de postincremento, una declaración como "a = (b ++ + c ++);" se traduciría efectivamente como "a = postinc1 (b) + postinc1 (c); postinc2 (b); postinc2 (c);"; la segunda parte del incremento posterior sería una función vacía. En la implementación real, las llamadas postinc2 () probablemente ocurran con frecuencia mientras que otros resultados están en la pila de evaluación; eso no debería ser demasiado difícil de implementar para un compilador.

En el caso de "&&" o "||", la primera parte del operador simplemente operaría en el operando izquierdo; si devuelve un valor distinto de cero (para &&) o distinto de cero (para ||), entonces la segunda parte operaría en ambos operandos.

En el caso de "?" / ":", La primera parte del operador operaría solo en el primer operando. Si devuelve un valor distinto de cero, la segunda parte operaría en los parámetros primero y segundo; de lo contrario, la tercera parte operaría en los parámetros primero y tercero.

¿Algún idioma hace algo así? Parece extraño que C ++ permita que los operadores se redefinan de forma que rompan el comportamiento de la secuencia, pero no permite que se redefinan de forma que se conserven.


0
2017-09-16 23:04



El compilador utiliza el argumento int para distinguir entre los operadores de incremento prefijo y postfijo. Para llamadas implícitas, el valor predeterminado es cero por lo que en realidad no hace tanta diferencia en la funcionalidad del operador sobrecargado ...


0
2017-11-23 06:36