2012-07-25 13 views
10

Duplicar posible:
Functions with const arguments and Overloading¿Por qué los calificadores const en los argumentos de función se usan para sobrecargar la resolución?

estoy bastante confundido por la sobrecarga y reglas de declaración const. Aquí hay dos cosas que me desconciertan, tal vez puedas ayudarme a encontrar el malentendido más profundo en mi cabeza que hace que me resulten desconcertantes. ;)

Primera edición:

Mi compilador permite esto:

void f(int & x) { 
    std::cout << "plain f" << std::endl; 
} 
void f(const int & x) { 
    std::cout << "const f" << std::endl; 
} 

Pero la siguiente provoca un error de compilación (función ya tiene un cuerpo):

void f(int x) { 
    std::cout << "plain f" << std::endl; 
} 
void f(const int x) { 
    std::cout << "const f" << std::endl; 
} 

que supongo tiene sentido porque pensé que la const estaba solo allí para decirle al compilador que el objeto que se pasa no se cambia y en el segundo caso se copia de todos modos. Pero si eso es correcto, ¿por qué puedo sobrecargar funciones usando const?

En otras palabras, ¿por qué si utilizo la versión de compilación y llamar a las funciones de la siguiente manera:

int x1 = 5; 
    const int x2 = 5; 
    f(x1); 
    f(x2); 

Cómo llego "f normal" y "f const" en lugar de "f const" dos veces? Aparentemente ahora también estoy usando el const para decirle al compilador qué función llamar no solo para que la referencia no cambie. Esto se vuelve más confuso porque si elimino la versión "simple", funciona bien y llama a la versión "const" dos veces.

¿Cuál es mi pregunta actual? Me gustaría saber cuáles son las ideas detrás de este comportamiento porque, de lo contrario, memorizarlo es muy difícil.

+0

Los calificadores 'const' de nivel superior en los parámetros de la función _se eliminan_ al determinar la firma de una función. 'void f (int)' y 'void f (const int)' se refieren a la misma función. El nivel superior 'const' no se usa para la resolución de sobrecarga. 'const' más abajo en un tipo derivado (como en' const int & ') influye en los tipos de parámetros de función y, por lo tanto, en la firma de la función. –

+0

Vea también: http://stackoverflow.com/questions/4212932/defining-a-function-with-different-signature –

+0

@CharlesBailey Gracias por los enlaces. De alguna manera no los encontré, lo siento. – Sarien

Respuesta

1

me pareció que el const estaba allí sólo para decirle al compilador que ser el objeto pasado, no se cambia y en el segundo caso se copia todos modos

Estás en lo correcto. Porque en el segundo caso se copia de todos modos, por lo que el const no hace ninguna diferencia para la persona que llama, el estándar define que void f(const int x) y void f(int x) tienen la misma firma. Por lo tanto, colisionan, intentas definir la misma función dos veces.

Debido a que en el primer caso, no es copiado de todos modos, y void f(const int &x)void f(int &x) tienen diferentes firmas. Por lo tanto, se sobrecargan.

En el primer caso, está prohibido llamar a la versión de int&f con x2 como argumento, ya que esto crearía una referencia no const a un objeto constante sin ninguna conversión explícita a la vista. Hacer eso derrota el propósito del sistema const (que es que si quieres romper la seguridad const, tienes que hacerlo explícitamente con un molde). Por lo tanto, tiene sentido tener sobrecargas const y no const de funciones con parámetros de referencia.

En su segundo caso, no existe relación entre la constidad del origen de una copia y la constidad del destino. Puedes inicializar una variable const desde una const one o una sin const desde una const one. Esto no causa problemas y no rompe la seguridad. Es por eso que el estándar lo aclara al aclarar que sus dos versiones "diferentes" de f son en realidad la misma función.

+0

Así que tal vez mi pregunta se reduce a: ¿Por qué querría usar la función sin conexión (cuando llamo)? Para elaborar un poco: ¿Por qué debería querer llamar a f (int & x) cuando tengo f (int const & x)? Parece ser difícil distinguir cuál se llama y es completamente confuso. – Sarien

+0

Supongo que se relaciona con el hecho de que el "const" en mi cabeza me dice algo sobre el comportamiento de la función (no cambia esta referencia) y ahora se está utilizando para decidir qué función usar. – Sarien

+0

@CorporalTouchy: * no se puede * llamar a la función no const con un argumento const, porque se permite hacer algo como 'void f (int & x) {x = 6;}'. Es por eso que la sobrecarga 'f (const int & x)' se selecciona cuando la pasa 'x2'. Cuando lo pasa 'x1', la sobrecarga sin const se selecciona, porque en efecto al proporcionar un lvalue no const como argumento, le está dando permiso para modificar su variable. De hecho, el cuerpo de su función no modifica nada, por lo que en este caso seguro, es difícil ver por qué la diferencia importa. –

4

n3337 13,1

[Nota: Como se especifica en 8.3.5, declaraciones de función que tienen declaraciones de parámetros equivalentes declaran la misma función y por lo tanto no puede sobrecargarse: ffer sólo en la presencia o ausencia

- Declaraciones de parámetros que di3 de const y/o volátil son equivalentes. Es decir, los const y especificadores de tipos volátiles para cada tipo de parámetro se ignoran cuando determina qué función se declara, define o llama. [ Ejemplo:

typedef const int cInt; 
int f(int); 
int f(const int); // redeclaration of f(int) 
int f(int) { /* ... */ } // definition of f(int) 
int f(cInt) { /* ... */ } // error: redefinition of f(int) 

- extremo ejemplo] Sólo el const y volátiles de tipo especificadores en la más externa nivel del tipo de parámetro especifica- ción se ignora en este moda; Los especificadores de tipos const y volátiles enterrados dentro de un parámetro tipo de especificación son significativos y se pueden usar para distinguir declaraciones de funciones sobrecargadas.124 En particular, para cualquier tipo T, "puntero a T", "puntero a const T" y "Puntero a T volátil" son considerados tipos de parámetros distintos, como "referencia a T", "referencia a const T" y "referencia a T. volátil".”

+0

Todavía estaría interesado en una razón para este comportamiento, ya que parece ser un confuso doble significado para const. (Me gustaría saber por qué se define así en el estándar). – Sarien

+2

@CorporalTouchy: cuando pasa un parámetro por valor, crea una copia. Si esa copia es 'const' no tiene relación con el comportamiento del código de llamada, por lo que no hay razón para distinguirlos del lado de la llamada. –

Cuestiones relacionadas