为什么类成员函数使用相同名称阴影自由函数
Why class member functions shadow free functions with same name?
最近我注意到,成员函数在类内完全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
}
};
我不是在问如何从类内部调用阴影自由函数。我想知道的是这个设计背后的原理。
对于非限定名称查找,一次只考虑一个作用域,如果在该作用域中的搜索没有产生任何结果,则搜索下一个更高的作用域。在您的情况下,只搜索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++
的一句话,或者当时确实是委员会的成员),但我的第一个猜测是,正如你所展示的那样,在某些情况下会完全失败。人们很容易忘记在某个时间有多少东西在范围内。此外,重载解析可能相当复杂,并且可能存在默认参数和转换。因此,在这种情况下,我宁愿拥有最有限的范围,以始终确定确切的名称。
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- MFC 用于计算控件的高光、阴影等的算法或函数是什么?
- opencv 中的哪个函数可以检测和去除物体的阴影
- 命名空间中函数的阴影
- 为什么类成员函数使用相同名称阴影自由函数
- 当构造函数上只有一个参数时,会对参数进行阴影处理