为什么编译器在重载时停止名称查找
Why does the compiler stops the name lookup on overloads?
我刚刚读了这篇文章:c++名称空间的乐趣在这里,作者通过使用命名空间表明编译器在遇到第一个重载时停止查找。
namespace A
{
void f(int x); // like our std::sqrt(double)
}
namespace B
{
struct S {}; // user-defined type with associated namespace B
void f(S);
void f(int, int);
void test1()
{
using namespace A; // using DIRECTIVE
f(1); // ERROR namespace A is not considered because
// B contains two overloads for 'f'
f(1,2); // OK B::f(int,int)
f(B::S()); // OK B::f(S)
}
void test2()
{
using A::f; // using DECLARATION
f(1); // OK A::f(int)
f(1,2); // ERROR A::f hides B::f(int,int)
f(B::S()); // OK B::f(S) due to ADL!
}
}
namespace C
{
void test3()
{
using namespace A; // using DIRECTIVE
f(1); // OK A::f(int)
f(B::S()); // OK B::f(S) due to ADL!
}
void test4()
{
using A::f; // using DECLARATION
f(1); // OK A::f(int)
f(B::S()); // OK B::f(S) due to ADL!
}
}
为什么编译器应该停止?
编辑#1:问题确实是:为什么标准这么说?
谢谢你的回答!
编译器在遇到第一个
时停止查找重载
不,当遇到第一个时,它不会停止" 否则你不能同时找到B::f(int,int)
和B::f(S)
。
查找给定作用域中的所有重载(不仅是第一个),但不会在更远的作用域中进一步查找。
这就像c++中的所有名称查找一样,如果你有一个全局变量var
,在某些函数中你也有一个局部变量var
,在函数中使用名称将引用局部变量。这样更有用,你更有可能使用在附近声明的变量,因为它在相关代码中。
如果有人递给你一封信,让你把它交给弗雷德,他站在几米远的地方,戴着一个徽章,上面写着"我是弗雷德",你会无视他,走到外面,继续寻找世界上其他叫弗雷德的人吗?
using A::f隐藏了之前所有"f"的定义。
可以使用
void test2()
{
f(1,2); // ERROR A::f hides B::f(int,int)
using A::f; // using DECLARATION
f(1); // OK A::f(int)
f(B::S()); // OK B::f(S) due to ADL!
}
或
void test2()
{
using A::f; // using DECLARATION
f(1); // OK A::f(int)
using B::f;
f(1,2); // ERROR A::f hides B::f(int,int)
f(B::S()); // OK B::f(S) due to ADL!
}
最佳做法是调用
void test2()
{
A::f(1); // OK A::f(int)
B::f(1,2); // ERROR A::f hides B::f(int,int)
B::f(B::S()); // OK B::f(S) due to ADL!
}
它明确地提到了使用哪个函数
显而易见的答案是:因为标准是这么说的。的原因标准说这样做是为了让你的程序更健壮:假设您已经编写了您的类:
class MyClass : public SomeBase
{
private:
void f( int );
void g()
{
f( 'x' );
}
};
现在,在g
的调用位置,编译器将找到MyClass::f(int)
,只有MyClass::f(int)
。这是可能是你想要的。你不想要的是编译器突然开始寻找SomeBase::f(char)
,如果有人碰巧添加它。(至少基本原理是这样的。)
最后:编译器不总是停止查找当它找到一个符号。例如,ADL需要考虑在内。规则在模板中略有不同,取决于符号是否依赖
相关文章:
- 如何允许编译器查找通过 brew 安装的库
- 编译器在C++中调用另一个函数时,在参数中查找已删除的构造函数
- 编译器无法链接/查找 GLFW
- 为什么 C++ 编译器在"c:program filesgnu emacsinclude"中查找包含文件?
- 编译器正在查找.当"实施"完全在"我的"中时的CPP文件.HPP文件
- Visual Studio 2015资源视图和资源编译器使用不同的方法在项目目录中查找图标文件.如何修复
- C++使用旧编译器GCC 4.4.0在结构列表中查找字符串
- 有没有办法告诉 g++ 编译器,而不是在某个 -I 路径中查找包含标头
- 哪个查找规则阻止编译器查找函数
- 不同编译器的名称查找的不一致性
- 支持与参数有关的查找的编译器
- 如何使 C/C++ 编译器在用户指定的路径中查找标头
- 编译器查找头文件,但不查找 cpp 文件
- 包括查找编译器选项的外部标头
- C++编译器多次查找标头中定义的值
- 查找库是由SJLJ还是DWARF2编译器编译的
- 编译器差异:别名解析和名称查找之间的交互
- 理解运算符查找;哪个编译器是正确的
- 在GNU编译器中,typedef的名称查找有缺陷
- 如何查找编译器实现细节