2010-09-09 23 views
12

Tomar nota del siguiente código C++:¿Por qué una declaración de función con un argumento const permite llamar a una función con un argumento no const?

#include <iostream> 
using std::cout; 

int foo (const int); 

int main() 
{ 
    cout << foo(3); 
} 

int foo (int a) 
{ 
    a++; 
    return a; 
} 

en cuenta que el prototipo de foo() toma una const int y que la definición tiene un int. Esta compilación sin ningún error ...

¿Por qué no hay errores de compilación?

+0

Por favor, consultar acerca punteros. – alternative

+14

@mathepic: ¿Qué tiene que ver este código con los punteros? – casablanca

+0

@casablanca Todo - Parece que hes mezclando const int e int como siendo int e int *. – alternative

Respuesta

31

Porque a la persona que llama de la función foo no le importa si foo modifica su copia de la variable o no.

Específicamente en el estándar de C++ 03, los siguientes 2 fragmentos explicar exactamente por qué:

C++ 03 Sección: 13.2-1

Dos declaraciones de función del mismo nombre se refieren a la misma función si están en el mismo ámbito y tienen declaraciones de parámetros equivalentes (13.1).

C++ 03 Sección: 13.1-3

declaraciones de parámetros que difieren sólo en la presencia o ausencia de const y/o volátil son equivalentes. Solo los especificadores de tipos const y volátiles en el nivel más externo de la especificación de tipo de parámetro se ignoran de esta manera; Los especificadores de tipos const y volátiles enterrados dentro de una especificación de tipo de parámetro son significativos y se pueden usar para distinguir declaraciones de funciones sobrecargadas.

+0

+1 para cotizar la especificación. – casablanca

+2

+1: La segunda cita es fácilmente malentendida en la ausencia de lo que sigue en el estándar "Solo los especificadores de tipos const y volátiles en el nivel más externo de la especificación de tipo de parámetro son ignorados de esta manera; const y volátiles especificadores de tipo enterrados dentro de una especificación de tipo de parámetro son significativos y se pueden usar para distinguir declaraciones de funciones sobrecargadas.112) ". Entonces 'int const * p' e 'int volátil * p' son diferentes – Chubsdad

+0

@Chubsdad: De acuerdo Debería haber puesto más allí, lo he agregado. Gracias. –

-2
int foo (const int a) 
{ 
    a++; 
    return a; 
} 

Eso va a lanzar un error durante la compilación.

+1

Lo hará, pero ¿qué tiene eso que ver con la pregunta que se hace? –

12

El nivel superior const (es decir, que se aplica al valor que se pasa, no es algo a lo que apunta o refiere) afecta solo a la implementación, no a la interfaz, de una función. El compilador lo ignora desde el punto de vista de la interfaz (es decir, el lado de la llamada) y lo impone solo en la implementación (es decir, código en el cuerpo de la función).

+5

+1 por * no *, citando las especificaciones y, en su lugar, explicando a un usuario obviamente novato cuál es la razón detrás de este comportamiento. –

+0

Me gusta mucho ver el estándar citado, siempre que la cita tenga sentido despojado de su contexto; es, después de todo, el punto definitivo. – Steve314

+3

@ Steve314: ¿Cómo * atreves * implica que decir algo es menos definitivo que citar el estándar! :-) –

2

Como otros han explicado, la norma dice que está bien, y que el compilador puede permitirse ser indulgentes con la aplicación de esta, ya que no afecta a la persona que llama, pero nadie respondió por qué el compilador debe elegir ser indulgente. No es particularmente indulgente en general, y un programador que acaba de mirar la interfaz y luego se zambulle en la implementación puede tener en mente que un parámetro es const cuando no lo es o viceversa, no es algo bueno.

Esta indulgencia permite cambios de implementación sin modificar los encabezados, que al usar herramientas de creación tradicionales desencadena la recompilación del código de cliente. Esto puede ser un problema serio en el desarrollo de escala empresarial, donde un cambio no sustancial en un encabezado de bajo nivel (por ejemplo, el registro) puede forzar la reconstrucción de prácticamente todos los objetos entre él y las aplicaciones ... desperdiciando miles de horas de tiempo de CPU y retrasando a todos y todo lo que espera en las compilaciones.

Por lo tanto, es feo, pero una concesión práctica.

También he respondido otra pregunta similar que analiza por qué la sobrecarga de f (const T) y no está permitido f (T) - pueda ser de interés para cualquiera que lea esto - Top-level const doesn't influence a function signature

+0

No lo veo como lenidad. Puedo escribir una declaración y asignación 'const int x = y;' incluso si sucede que es una variable no const. Es importante que el valor de x permanezca constante en su tiempo de vida, no que el valor de y permanezca igualmente constante. También puedo escribir 'int x = y;' incluso si y pasa a ser una constante.El paso de parámetros está haciendo más o menos lo mismo. No se trata de una cuestión de lenidad porque no hay ninguna regla que se pueda aplicar: el parámetro formal recibe un valor (no una variable) por la llamada, y no hay ninguna razón por la que el origen de ese valor no sea modificable. – Steve314

+0

@Steve: el aspecto de indulgencia se relaciona con la aceptación de una declaración que declara que usted podrá o no podrá modificar el parámetro, y luego una definición que no concuerda. Como dices, cualquiera estaría bien, pero eso no significa que sean equivalentes o consistentes. –

+0

En mi forma de pensar lo hace. Un valor simplemente no tiene 'const'; es una propiedad de variables, miembros, parámetros, etc., pero no de valores. Los valores son siempre inmutables de todos modos, 5 es siempre 5 y así sucesivamente. Esta idea simple es muy buena para predecir cómo se comportará C++ ya sea que esté buscando inicializaciones variables, parámetros y sobrecarga, o lo que sea. En cualquier caso, los parámetros siempre se comportan de manera muy similar a las variables locales; solo el método de inicialización difiere, y eso es consistente con la regla anterior. Para la sobrecarga para preocuparse por const de nivel superior me parece muy inconsistente. – Steve314

Cuestiones relacionadas