It recently came to my attention该成员在课堂内使用相同名称的完全 shadow 免费函数。完全我的意思是,每个具有相同名称的自由函数根本不考虑重载解析。我可以理解为什么这样做会像这样:
void f();
struct S
{
void f();
void g()
{
f(); // calls S::f instead of ::f
}
};
其中函数具有相同的签名,其唯一自然的变量作用域以相同的方式工作。但是为什么要禁止在自由函数具有不同签名的无意义调用:
void f();
struct S
{
void f(int x);
void g()
{
f(); // fails to compile attempting to call S::f, which has wrong signature
}
};
我不是问如何从类中调用 shadowed 自由函数。我想知道的是这种设计背后的基本原理。
答案 0 :(得分:7)
对于非限定名称查找,一次只考虑一个范围,如果该范围内的搜索未产生任何结果,则搜索下一个更高范围。在您的情况下,只搜索S
的范围。
但是为什么禁止自由函数具有不同签名的无意义调用:
问题是名称查找除了名称标识符之外没有任何其他内容。你完全忘记了你想要调用一个函数,它只是看到一个标识符。如果您只使用auto x = f;
,则会发生相同的名称查找,如果您这样想,那么您只需要非常有限的搜索范围就有很好的理由。任何其他东西都会让用户感到惊讶。
答案 1 :(得分:3)
有一个特殊的,非常令人惊讶的规则(但它不适用于您的示例)声明一旦通过名称查找找到类成员名称,就不会搜索任何命名空间范围:
#include <string>
struct C {
std::string s;
explicit C (std::string);
void swap (C& rhs) {
swap (s, rhs.s); // error: swap is C::swap
}
};
void swap (C& lhs, C& rhs) {
swap (lhs.s, rhs.s); // std::swap(string,string)
}
IMO,这很疯狂。
但是为什么禁止自由函数具有不同签名的无意义调用:
在重载分辨率之前发生名称查找:
规则足够复杂,在重载和名称查找之间没有“反馈”。我建议简化(比如删除成员隐藏命名空间范围名称规则,并删除模糊名称查找)而不是复杂化。
答案 2 :(得分:2)
我无法提供一个权威的答案(也许有人记得Design and Evolution of C++
的引用或者当时已经在委员会中的引用),但我的第一个猜测是在你展示的情况下完全失败。很容易忘记在某个时间范围内有多少东西。此外,重载解析可能非常复杂,可能存在默认参数和转换。所以我宁愿在这种情况下拥有最有限的范围,以确保始终确切地调用它。