为什么在下一个程序中,成员函数foo优先于全局foo,尽管全局foo与类型相匹配?
#include <iostream>
using namespace std;
void foo(double val) { cout << "double\n";}
class obj {
public:
void callFoo() { foo(6.4); }
private:
void foo(int val) {cout << "class member foo\n"; }
};
int main() {
obj o;
o.callFoo();
}
答案 0 :(得分:9)
因为可以在类范围内找到名为foo
的成员函数,然后名称查找将停止,因此不会考虑全局版本foo
重载决策,即使全局版本更合适。这是一种名称隐藏。
如果您想调用全局版本,可以::foo(6.4);
明确地调用它。
here是将全局函数纳入重载决策的解决方法。
的参考答案 1 :(得分:7)
考虑如果在代码库中声明某处的全局函数(可能有几个#include
语句)将会胜过声明的<{1}}成员函数会发生什么在班级本身 ......
这意味着,如果您想要安全地玩,您必须完全限定每次调用成员函数 ...
class obj
...而不必限定实际引用全球功能的不太可能的情况。
this->foo();
这被称为&#34;最少惊喜的概念&#34;。
答案 2 :(得分:3)
方法重载的原则之一是具体应该胜过一般。在您的示例中,成员方法将始终比全局方法更具体。
答案 3 :(得分:3)
通常,当嵌套作用域时,在内部作用域中使用该名称时,内部作用域中声明的任何名称都会隐藏外部作用域中具有相同名称的任何实体。因此,在这种情况下,当在类范围中使用时,类中声明的名称将隐藏在封闭命名空间中声明的名称。
如果符合条件,外部名称仍然可用;在这种情况下,在全局命名空间中,它可以::foo
。
答案 4 :(得分:1)
您可以将其视为增加&#34;专业化&#34;当你从全局命名空间移动到你的类,嵌套类等任何嵌套命名空间时,直到所涉及的成员函数。如果你说&#34; foo&#34;在这种内在的背景下,一个更专业的&#34;可以预期foo
与呼叫者更相关。此外,如果优先使用全局的,那么有人将符号添加到较少的&#34;专门的&#34; scope可能会破坏定义同名符号的类,从而撤消命名空间和标识符范围的许多好处。基本的想法是,您的班级有很多自由使用有意义但简洁的标识符 - 这些标识符可能会被您应用程序中的其他代码使用 - 但只有在该标识符的含义不可用时才能使用在最局部的范围内,它开始越来越远。
答案 5 :(得分:1)
在使用相同名称的标识符,本地范围,类成员(类范围),全局范围时,范围解析的优先级(默认)