7

It recently came to my attention ese miembro funciones completamente sombra funciones gratuitas con el mismo nombre cuando dentro de la clase. Y por completo quiero decir que cada función libre con el mismo nombre no se considera en absoluto para la resolución de sobrecarga. Puedo entender por qué se hace con somwthing así:¿Por qué las funciones miembro de la clase sombrean funciones libres con el mismo nombre?

void f(); 

struct S 
{ 
    void f(); 

    void g() 
    { 
     f(); // calls S::f instead of ::f 
    } 
}; 

donde las funciones tienen firmas idénticas, su único natural como ámbito de las variables funciona de la misma manera. Pero ¿por qué prohibir las llamadas unambigious donde la función libre tiene diferentes firmas como esto:

void f(); 

struct S 
{ 
    void f(int x); 

    void g() 
    { 
     f(); // fails to compile attempting to call S::f, which has wrong signature 
    } 
}; 

No estoy pidiendo cómo llamar a un ensombrecidos función libre desde el interior de la clase. Lo que quiero saber es la razón de ser de este diseño.

+1

Es posible que debas preguntarle a Bjarne Stroustrup! – peacemaker

+1

Buscar de esta manera significa que la lista de funciones candidatas generadas es siempre pequeña. Eso es bueno para los tiempos de compilación, se puede imaginar que si buscaba todos los posibles candidatos (incluyendo ADL) y había muchas plantillas, muy rápidamente se volvería muy lento. También refleja el uso y la semántica deseada en la mayoría de los casos. Normalmente cuando dices 'foo' el' foo' que estás pensando es el más cercano. Si no es el más cercano, es probable que se haya equivocado. Un error es mejor que cosas raras que suceden en el tiempo de ejecución. Mantener las cosas locales es un buen comportamiento. – Flexo

+2

puede disfrutar de esta presentación en Búsqueda de nombres: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of -n – MFH

Respuesta

6

Para la búsqueda de nombres no calificados, se considera solo un ámbito a la vez, y si la búsqueda en ese ámbito no arroja ningún resultado, se busca el siguiente alcance superior. En su caso, solo se busca el alcance S.

Pero por qué prohibir las llamadas unambigious donde la función libre tiene diferentes firmas como esto:

El problema es que la búsqueda de nombres no se ocupa con cualquier cosa menos el nombre, el identificador . Es completamente ajeno al hecho de que desea llamar a una función, solo ve un identificador. La búsqueda del mismo nombre ocurre si solo usa auto x = f;, y si lo piensa de esa manera, hay muy buenas razones por las que solo desea un alcance muy limitado para buscar. Cualquier otra cosa simplemente sorprendería al usuario.

+1

"_El problema es que la búsqueda de nombre no se refiere a nada más que el nombre, el identificador._" En casi todos los idiomas, eso es cierto. No en C++. – curiousguy

2

No puedo proporcionar una respuesta autorizada (tal vez algunos recuerden una cita de Design and Evolution of C++ o de hecho haya estado en el comité en ese momento), pero mi primera conjetura sería fallar exactamente en los casos que demuestre. Es fácil olvidar cuántas cosas están en el alcance en un momento determinado. Además, la resolución de sobrecarga puede ser bastante compleja y puede haber argumentos predeterminados y conversión. Así que prefiero tener el alcance más limitado en ese caso para estar siempre seguro de cómo se llama exactamente.

+0

Especulación, pero esa es mi corazonada también. Es difícil distinguir entre confiar en locas búsquedas remotas y errores tipográficos. – Flexo

+0

"_Es fácil olvidar cuántas cosas están en el alcance en un momento determinado._" este es un argumento extremadamente fuerte para no esconder el nombre aquí. – curiousguy

3

Hay una especial, muy sorprendente, la regla (pero no se aplica a su ejemplo) que indica que una vez que un nombre de miembro clase es encontrado por la búsqueda de nombres, no hay ámbitos de espacio de nombres se buscan:

#include <string> 

struct C { 
    std::string s; 

    explicit C (std::string); 

    void swap (C& rhs) { 
     swap (s, rhs.s); // error: swap is C::swap 
    } 
}; 

void swap (C& lhs, C& rhs) { 
    swap (lhs.s, rhs.s); // std::swap(string,string) 
} 

IMO, esto es locura.

Pero por qué prohibir las llamadas unambigious donde la función libre tiene diferentes firmas como esto:

búsqueda de nombre ocurre antes de la sobrecarga de resolución:

  • si la búsqueda es ambigua, no se realiza la resolución sobrecarga.
  • Si no se encuentra una función viable por búsqueda de nombres, no se intenta ninguna otra ronda de búsqueda.

Los reglas son suficientemente complejo sin "retroalimentación" entre sobrecarga y búsqueda de nombre. Sugiero que la simplificación (como eliminar el miembro oculta la regla del nombre del ámbito del espacio de nombres y eliminar la búsqueda ambigua del nombre) en lugar de la complejización.

+0

Esto no es tan loco como crees. La búsqueda de nombres se detiene cuando se encuentra una coincidencia (en algún lugar alrededor de §3.4), y se da una orden precisa de adentro hacia afuera. Entonces, si se encuentra un miembro con un nombre, se detiene. No sorpresa. – Damon

+0

@Damon "La búsqueda _Name se detiene cuando se encuentra una coincidencia_ no", como muestra mi segunda llamada 'swap' – curiousguy

Cuestiones relacionadas