2012-02-21 19 views
7

Mam dwa przestrzenie nazw, z których każdy ma funkcję o tej samej nazwie. Jeśli z jednej z przestrzeni nazw chcę wywołać funkcję, która pasuje do najlepszej. Z funkcji w NamespaceA, jeśli zadzwonię do MyFunction (...), oczywiście korzysta z funkcji w NamespaceA. Jednakże, jeśli dodaję "using NamespaceB :: MyFunction", będę oczekiwał zachowania, które opisałem. Jednak widzę, że ZAWSZE znajduje funkcję NamespaceB, mimo że jestem w NamespaceA. JEDNAKŻE, JEŻELI TAKŻE dodaję używanie :: NamespaceA (nawet jeśli jestem już w NamespaceA), działa tak, jak się spodziewam. Demonstracja znajduje się poniżej. Czy ktoś może wyjaśnić, jak to działa?Porządek wyszukiwania przestrzeni nazw

#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

Jednym słowem, "źle" . Jeśli chcesz przeciążyć 'MyFunction', po prostu umieść obie implementacje w tej samej przestrzeni nazw i pozwól mechanizmowi przeładowczemu kompilatora dowiedzieć się, który jest najlepszy. –

+0

Czy próbowałeś tego w dwóch różnych kompilatorach, czy próbowałeś dowiedzieć się, jakie powinno być standardowe zachowanie? –

+0

@DavidThornley: To jest standardowe zachowanie. Chociaż masz rację, że OP powinien był przejść test sprawdzający. –

Odpowiedz

0

Uważam, że przestrzenie nazw używają tych samych reguł określania zakresu jako zmiennych. więc jeśli masz lokalny obszar nazw, odnośniki pojawią się tam najpierw przed przejściem do zewnętrznego zakresu.

Nie jestem pewien, jakie są reguły dotyczące sytuacji, w której zaimportowano dwa przestrzenie nazw o tych samych nazwach funkcji, ale należy zawsze w pełni kwalifikować wywołania funkcji w tym scenariuszu tylko dla jasności, zamiast polegać na pewnym niuansie implementacji języka dla przestrzeni nazw, których ludzie mogą nie znać.

2

Ma to związek z kolejnością szukania nazwy w różnych częściach programu. W przypadku sytuacji, o której wspomniałeś, ma to związek z zakresem szukanego bloku funkcji najwyższego poziomu przed otaczającym obszarem nazw. Zasadniczo deklaracja using przenosi tę nazwę do zakresu najwyższego poziomu DoSomething, a ponieważ zasięg ten jest rozpatrywany przed zasięgiem otaczającym przestrzeń nazw, wówczas jeśli znaleziono tam funkcję dopasowującą, zakres otaczającego obszaru nazw nie jest brany pod uwagę.

Przeanalizowałem wiele rzeczy, które nie są istotne w twoim przykładzie (na przykład, jeśli argument nie był typem wbudowanym, to uwierz lub nie, nazwy z zakresu, w którym zdefiniowano ten typ Cała historia, patrz sekcja 3.4. here. To dość przerażające, około 13 stron, aby opisać te wszystkie rzeczy, ale nie przejmuj się tym, chyba że naprawdę jesteś ciekawy, ponieważ większość rzeczy jest dostępna. że "działa w sposób, jakiego oczekujesz", mniej lub bardziej.Ten dokument nie jest prawdziwym standardem, ale faktycznie roboczym projektem z pewnymi poprawkami, więc jest to w zasadzie prawdziwy standard C++ plus kilka poprawek.

+1

Czy to faktycznie pierwszy szkic C++ 1x/C++ 2x? –

+0

Tak, możesz myśleć o tym w ten sposób, ale bardziej przypomina "C++ 11 z drobnymi poprawkami błędów". – chisophugis

+0

C++ 03 to C++ 98 z niewielkimi poprawkami błędów i to był prawdziwy standard. –

0

Krótki odpowiedź: Lokalna zdefiniowana nazwa i nazwa zadeklarowana przez deklarację użycia ukrywa nazwy nielokalne.

Szczegółowa odpowiedź:

Twoje pytanie jest bardzo interesująca. Nie otworzyłem standardów dla tego pytania na C++ 98,03,11, ale otwórz Bjarne Stroustrup's book

Przestrzeń nazw - to nazwany zakres.Szczegółowość można wyeliminować za pomocą dwóch technik:

  • utworzyć synonimem używając NS :: x; (Przy użyciu deklaracja)
  • utworzyć synonim dla wszystkich zmiennych z używając nazw NS :: x; (Przy użyciu dyrektywą)

Odpowiedź na to pytanie jest tutaj:

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

Bonus z przeciwnej sytuacji:

Także jeśli

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

zmiana

using namespace NamespaceB; 

Następnie ze względu na tekst poniżej uzyskać sytuację z połączeniami tylko void MyFunction (int Object)

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

Dodatkowy kod do zabawy:

#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; 
} 
Powiązane problemy