隐藏自由函数的成员函数
member function hiding free function
void foo(int)
{
}
class X
{
void foo()
{
}
void bar()
{
foo(42);
// error: no matching function for call to 'X::foo(int)'
// note: candidate is:
// note: void X::foo()
// note: candidate expects 0 arguments, 1 provided
}
};
为什么C++无法调用 free 函数(这是唯一具有正确签名的函数(?
因为这两个标识符在不同的作用域中定义,并且重载解析只涉及同一作用域中的函数。一旦编译器发现该类有foo
,它就会停止爬升到更宽的范围(C++11 §3.4.1/1(,因此自由函数foo
被隐藏。
您需要使用限定名来引用全局foo
:
::foo(42);
合乎逻辑的原因是一致性。
- 假设按照建议,编译器解析
foo(42)
::foo(int)
. - 现在过了一段时间,如果您将
X::foo()
更改为X::foo(int)
那么foo(42)
将解决X::foo(int)
。这是不一致的。
这也是派生类函数在名称相似时隐藏基类函数的原因。
这种情况可以通过两种方式解决;
(1( 提供完全限定的名称(例如 ::foo(42)
(
(2(使用using
效用;例如
void bar()
{
using ::foo;
foo(42);
}
内部作用域中的名称隐藏外部作用域中的名称。无论是函数还是其他东西,或者您是否在类或命名空间中,都无关紧要。
仅当名称查找找到多个具有相同名称的函数时,重载解决方案才会启动,以尝试选择最适合调用的函数。
真的很喜欢你的问题。我也可以说,使用以下语法:
::foo(42);
但我可以说,在我看来,它更优雅,更好的编程,设置命名空间,所以你可以写这样的东西:
namespace MyNameSpace
{
void foo(int){}
class X
{
void foo(){}
void bar()
{
MyNameSpace::foo(42);
}
};
};
这是一件好事,因为Namespaces
允许将类、对象和函数分组到一个名称下。
PS:然后这可以帮助您理解没有任何命名空间时写::foo(42);
的含义。
我无法回答您问题的原因部分 - 我不知道语言规范中背后的理由是什么。
若要调用示例中的全局函数,请使用 :: 语法:
::foo(42);
这样做的原因是,编译器将首先查找匹配的函数名称,忽略返回值和参数。当在一个类中时,它将尝试在那里寻找匹配的成员(事实上,它将查看所有"向上"的作用域;本地作用域,函数作用域,类作用域,命名空间作用域,全局作用域等(。
X::foo
是第一个匹配的名称。然后(不是之前(它将尝试根据参数选择正确的重载(如果有多个声明((这就是您可以使用不同的参数重载同一函数的原因,但不能只重载不同的返回值(,然后它将检查返回值(如果有的话(。
- 如何使用指针传递给函数的数组中对象的函数成员
- c++构造函数成员初始化:传递参数
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 如何在C++通过公共函数访问私有函数成员?
- 解释了构造函数成员初始化列表
- 调用std::函数成员时内存损坏
- 是否可以为模板类的模板函数成员设置别名?
- 捕获 lambda 函数C++成员变量
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 获取与在模板参数中传递的函数成员类型相同的类
- 如何从公共函数成员访问地图私有成员
- C 构造函数成员分配优化
- 使用命名空间进行函数成员定义
- 函数成员作为 CUDA 内核的参数
- 模板基类函数成员的别名
- 函数成员中用于void和继承的enable_if
- 头文件中是否定义了一个很长的Class函数成员
- 类内/构造函数成员初始化
- 使用指向部分专用函数成员的指针自动填充向量
- 指向函数成员的指针