命名空间搜索顺序
Namespace search order
我有两个名称空间,每个名称空间都有一个同名的函数。如果我想从其中一个名称空间调用最匹配的函数。从NamespaceA中的一个函数,如果我调用MyFunction(…),它当然会使用命名空间a中的函数。但是,如果我添加了一个"usingNamespaceB::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;
}
这与程序的不同部分查找名称的顺序有关。对于您提到的情况,它与在封闭命名空间之前搜索函数的顶级块的范围有关。基本上,using
声明将该名称带入DoSomething
的顶级作用域,并且由于该作用域是在封闭命名空间作用域之前查找的,因此如果在那里找到匹配的函数,则不考虑封闭命名空间范围。
我已经掩饰了很多与你的例子无关的东西(例如,如果参数不是一个内置类型,那么,信不信由你,也可以考虑定义该类型的范围内的名称。关于整个故事,请参阅这里的第3.4节。这很可怕,大约13页来描述所有这些东西;但除非你真的很好奇,否则不要麻烦它,因为大多数东西都在那里,所以它"按照你期望的方式工作",或多或少。该文档不是真正的标准,但实际上是一个经过一些更正的工作草案,所以它基本上是真正的C++标准加上一些错误修复。
我相信名称空间使用与变量相同的作用域规则。因此,如果您有一个本地命名空间,那么在移动到外部作用域之前,将首先在那里进行查找。
对于导入了两个具有相同函数名的名称空间的情况,我不确定规则是什么,但为了清晰起见,应该始终完全限定该场景中的函数调用,而不是依赖于人们可能不熟悉的名称空间语言实现的一些细微差别。
简短回答:本地定义的名称和using声明声明的名称隐藏非本地名称。
详细答案:
你的问题很有趣。我没有为这个问题打开C++98,03,11的标准,但打开了Bjarne Stroustrup的书
命名空间-是一个命名的作用域。使用两种技术可以消除冗余:
- 使用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对象)的情况
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;
}
- 链接库时的默认目录上的GCC或G 路径搜索顺序
- treap 中的轮换会违反它的堆排序或二叉搜索树顺序吗?
- 正在覆盖find_package的默认搜索顺序
- void类数组顺序和二进制搜索使用
- 按字母顺序对数组进行二分搜索和排序 C++.
- 通过索引快速搜索,并将插入顺序保持在C 中
- 二进制搜索树中按顺序遍历的复杂性(使用迭代器)
- 使用递归的顺序和预序遍历 - 二叉搜索树 C++
- 二进制搜索树顺序树显示
- std::ostringstream 运算符重载搜索顺序
- 顺序搜索查询
- 模板类C++符号范围搜索顺序不同
- 二进制搜索树,按顺序遍历,步骤3逻辑辅助
- 如何更改共享库的搜索顺序
- 命名空间搜索顺序
- 按顺序搜索boost::multi_index,按顺序获取下一个元素
- 如何使用双向搜索按字母顺序将随机字符串添加到数组中
- 使用无重复键的链表进行顺序搜索
- 理解C++顺序搜索的问题
- 以相反顺序搜索multimap