命名空间搜索顺序

时间:2012-02-21 16:19:16

标签: c++

我有两个名称空间,每个名称空间都有一个具有相同名称的函数。如果从其中一个命名空间我想调用匹配最佳的函数。从NamespaceA中的函数,如果我调用MyFunction(...),当然它使用NamespaceA中的函数。但是,如果我添加一个'using NamespaceB :: MyFunction',我会期待我描述的行为。但是,我实际看到的是它总是找到NamespaceB函数,即使我在NamespaceA中。但是,如果我还添加了一个using :: NamespaceA(尽管我已经在NamespaceA中),它可以像我期望的那样工作。下面是一个演示。任何人都可以解释这是如何工作的吗?

#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;
}

3 个答案:

答案 0 :(得分:2)

它与查找程序的不同部分以查找名称的顺序有关。对于您提到的情况,它与在封闭命名空间之前搜索的函数顶级块的范围有关。基本上,using声明将该名称带入DoSomething的顶级范围,并且由于该范围在封闭的命名空间范围之前查找,因此如果在那里找到匹配的函数,那么封闭不考虑名称空间范围。

我已经掩盖了许多与你的例子无关的东西(例如,如果参数不是内置类型,那么,信不信由你,定义该类型的范围内的名称可以对于整个故事,请参阅第3.4节here。它非常可怕,大约有13页来描述所有这些内容;但除非你真的很好奇,否则不要理会它,因为大多数的东西有没有这样它“以你期望的方式工作”,或多或少。那个文件不是真正的标准,但实际上是一个带有一些修正的工作草案,所以它基本上是真正的C ++标准加上一些错误修正。

答案 1 :(得分:0)

我认为命名空间使用与变量相同的范围规则。因此,如果您有一个本地命名空间,那么在移动到外部范围之前,将首先进行查找。

我不确定您导入两个具有相同函数名称的命名空间的情况的规则是什么,但是为了清楚起见,您应该始终完全限定该场景中的函数调用,而不是依赖于某些细微差别人们可能不熟悉的命名空间的语言实现。

答案 2 :(得分:0)

简短回答:本地定义的名称和使用声明声明的名称隐藏了非本地名称。

详细解答:

你的问题非常有趣。我没有为这个问题打开 C ++ 98,03,11 的标准,但打开Bjarne Stroustrup's book

命名空间 - 是一个命名范围。可以使用两种技术消除详细程度:

  • 使用NS :: x创建的同义词; (使用声明)
  • 使用命名空间NS :: x为创建所有变量的同义词; (使用指示符)

你的问题的答案在这里:

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

相反情况下的奖励:

另外,如果你

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

更改为

using namespace NamespaceB;

然后你由于下面的文字得到的情况只调用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

可以使用的额外代码:

#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;
}