为什么类成员函数同名的无阴影函数?
-
12-12-2019 - |
题
它最近引起了我的注意 该成员的功能 完全 影子 类内时同名的自由函数。完全我的意思是,每个同名的免费函数根本不考虑重载解析。我可以理解为什么它是这样做的:
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
}
};
我不是在问如何打电话给 阴影,阴影 类内部的自由函数。我想知道的是这个设计背后的基本原理。
解决方案
对于非限定名称查找,一次只考虑一个范围,如果该范围中的搜索没有产生任何结果,则搜索下一个更高的范围。在你的情况下,只有 S
的范围进行搜索。
但是,为什么禁止明确的调用,其中自由功能具有不同的签名像这样:
问题是 名称查询 除了名字,什么都不关心。 标识符.它完全忘记了你想调用一个函数的事实,它只是看到一个标识符。相同的名称查找发生,如果你只是使用 auto x = f;
, ,如果你这样想,有很好的理由你只想要一个非常有限的范围来搜索。其他任何事情都会让用户感到惊讶。
其他提示
有一个特殊的,非常令人惊讶的规则(但它不适用于你的榜样)说明一个类成员名称是名称查找,没有搜索名称空间范围:
#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,这是疯狂的。
但为什么禁止禁止悬而未恒的呼叫,其中自由函数具有不同的签名,如下所示:
名称查找在重载过载决议之前发生:
- 如果查找是模糊的,则没有完成重载分辨率。
- 如果名称查找没有找到可行的函数,则尝试任何其他回合的查找。
规则是足够复杂的,没有“反馈”之间的重载和名称查找。我建议简化(如删除成员隐藏命名空间范围名称规则,并删除模糊名称查找)而不是复杂化。
我不能提供权威答案(也许有些人记得来自Design and Evolution of C++
的引用或者当时实际上已经在委员会上),但我的第一次猜测是在你所表现的情况下完全失败。很容易忘记某些时间有多少件事。另外,过载解决方案可能非常复杂,并且可能存在默认的参数和转换。所以我宁愿在这种情况下拥有最有限的范围,以始终确定正在调用什么。