2012-02-21 34 views
7

Tengo dos espacios de nombres que tienen una función con el mismo nombre. Si desde uno de los espacios de nombres quiero llamar a la función que coincida con la mejor. Desde una función en NamespaceA, si llamo a MyFunction (...), por supuesto, usa el que está en NamespaceA. Sin embargo, si agrego un 'using NamespaceB :: MyFunction', entonces esperaría el comportamiento que describí. Sin embargo, lo que realmente veo es que SIEMPRE encuentra la función NamespaceB, aunque estoy en NamespaceA. SIN EMBARGO, si TAMBIÉN agrego un using :: NamespaceA (aunque ya estoy en NamespaceA), funciona como esperaba. Una demostración es abajo. ¿Alguien puede explicar cómo funciona esto?Orden de búsqueda del espacio de nombres

#include <iostream> 

namespace NamespaceA 
{ 
    void DoSomething(); 
    void MyFunction(int object); 
} 

namespace NamespaceB 
{ 
    void MyFunction(float object); 
} 

namespace NamespaceA 
{ 
    void DoSomething() 
    { 
    using NamespaceA::MyFunction; // Note that without this line the lookup always fins the NamespaceB::MyFunction! 
    using NamespaceB::MyFunction; 

    MyFunction(1); 
    MyFunction(2.0f); 
    } 

    void MyFunction(int object) 
    { 
    std::cout << "int: " << object << std::endl; 
    } 
} 

namespace NamespaceB 
{ 
    void MyFunction(float object) 
    { 
    std::cout << "float: " << object << std::endl; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    NamespaceA::DoSomething(); 

    return 0; 
} 
+1

En una palabra, "mal" . Si desea sobrecargar 'MyFunction', simplemente ponga ambas implementaciones en el mismo espacio de nombres, y permita que el mecanismo de sobrecarga del compilador descubra cuál es la mejor coincidencia. –

+0

¿Ha probado esto en dos compiladores diferentes o ha intentado descubrir cuál debería ser el comportamiento estándar? –

+0

@DavidThornley: Este _es_ comportamiento estándar. Aunque tienes razón en eso, el OP debería haber hecho una prueba cruzada. –

Respuesta

0

creo que los espacios de nombres utilizan las mismas reglas de alcance que las variables. por lo tanto, si tiene un espacio de nombre local, las búsquedas se realizarán primero antes de pasar al ámbito externo.

No estoy seguro de cuáles son las reglas para la situación donde ha importado dos espacios de nombres con los mismos nombres de función, pero siempre debe calificar plenamente las llamadas de función en ese escenario solo por claridad, en lugar de basarse en algunos matices de la implementación del lenguaje para espacios de nombres con los que las personas pueden no estar familiarizadas.

2

Tiene que ver con el orden en que diferentes partes del programa se buscan para encontrar un nombre. Para la situación que menciona, tiene que ver con el alcance del bloque de nivel superior de la función que se busca antes del espacio de nombres adjunto. Básicamente, la declaración using lleva ese nombre al ámbito de nivel superior DoSomething, y como ese ámbito se mira antes que el ámbito del espacio de nombres adjunto, entonces si se encuentra allí una función coincidente, entonces no se considera el alcance del espacio de nombres adjunto.

He pasado por alto muchas cosas que no son relevantes en su ejemplo (por ejemplo, si el argumento no era un tipo incorporado, créalo o no, los nombres del ámbito donde se definió ese tipo) podría ser considerado también. Para la historia completa, vea la sección 3.4 here. Es bastante aterrador, alrededor de 13 páginas para describir todo esto, pero no se moleste a menos que realmente tenga curiosidad, porque la mayoría de las cosas están allí, así que que "funciona de la manera esperada", más o menos. Ese documento no es el estándar real, sino un borrador en funcionamiento con algunas correcciones, por lo que básicamente es el estándar real de C++ más algunas correcciones de errores

+1

¿Es efectivamente el primer borrador de C++ 1x/C++ 2x? –

+0

Sí, puedes pensarlo así, pero es más como "C++ 11 con algunas correcciones de errores menores". – chisophugis

+0

C++ 03 era C++ 98 con algunas correcciones de errores menores, y ese era un estándar real. –

0

corto respuesta: nombre definido local y el nombre declarado por una declaración de uso oculta nombres no locales.

respuesta detallada:

Su pregunta es muy interesante. No abrí standarts de C++ 98,03,11 para esa pregunta, pero abierto Bjarne Stroustrup's book

Espacio de nombre: es un ámbito con nombre.La verbosidad se puede eliminar utilizando dos técnicas:

  • crear también con usando NS :: x; (using-declaration)
  • crear todas las variables con usando el espacio de nombres NS :: x; (El uso de la directiva)

La respuesta a su pregunta es aquí:

Appendix B 10.1 
local definitions, and names defined with using-declaration hides 
the name of a non-local definitions. 

de experiencia con la situación opuesta:

También si

using NamespaceA::MyFunction; 
using NamespaceB::MyFunction; 

cambio de

using namespace NamespaceB; 

A continuación, debido al texto a continuación obtener situación de llamada sólo MyFunction vacío (int objeto)

8.2.8.2 
Names explicitly declared in namespace (also made with using declaration) 
have priority over the names made available by using directives 

código extra para jugar:

#include <iostream> 

// var in global namespace 
const char* one = "G_one"; 

// vars in named namespace 
namespace NS1 { 
    const char* one = "NS1_one"; 
    const char* two = "NS1_two"; 
    const char* three = "NS1_three"; 
} 

namespace NS2 { 
    const char* one = "NS2_one"; 
    const char* two = "NS2_two"; 
    const char* three = "NS2_three"; 
} 

int main(int argc, char *argv[]) 
{ 

    using namespace NS1;  // using-directive 
    using namespace NS2;  // using-directive 

    // const char* two = "L_two"; // local namespace 
    using NS2::two;    // using-declaration 

    // C++ rules 
    // Local names and names with using-declarations 
    // takes precedence over the name of the NS  
    std::cout << "two: " << two << std::endl; 

    //std::cout << "three: " << three << std::endl; // ambiguous symbol 

    // But the name in global-namespace does not have priority over imported name from namespace 
    //std::cout << "one: " << one << std::endl; // ambiguous symbol. Because wGlobal names does not have priority over 
    return 0; 
} 
Cuestiones relacionadas