为什么具有相同名称但不同签名的多个继承函数不会被视为重载函数?
以下代码片段在编译期间产生“对 foo 的模糊调用”错误,我想知道是否有任何方法可以解决此问题,而无需完全限定对 foo 的调用:
#include <iostream>
struct Base1{
void foo(int){
}
};
struct Base2{
void foo(float){
}
};
struct Derived : public Base1, public Base2{
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
所以,问题如标题所示。有想法吗?我的意思是,以下工作完美无缺:
#include <iostream>
struct Base{
void foo(int){
}
};
struct Derived : public Base{
void foo(float){
}
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
The following snippet produces an "ambigious call to foo" error during compilation, and I'd like to know if there is any way around this problem without fully qualifying the call to foo:
#include <iostream>
struct Base1{
void foo(int){
}
};
struct Base2{
void foo(float){
}
};
struct Derived : public Base1, public Base2{
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
So, question is as the title says. Ideas? I mean, the following works flawlessly:
#include <iostream>
struct Base{
void foo(int){
}
};
struct Derived : public Base{
void foo(float){
}
};
int main(){
Derived d;
d.foo(5);
std::cin.get();
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
成员查找规则在第 10.2/2 节中定义
因此,您可以使用
using
声明A::f
和B::f
来解决该歧义第二个代码可以完美地工作,因为
void foo(float)
位于 C 的作用域内。实际上 d.foo(5); 调用的是void foo(float)
而不是int
版本。Member lookup rules are defined in Section 10.2/2
So you can use the
using
declarationsA::f
andB::f
to resolve that ambiguityThe second code works flawlessly because
void foo(float)
is inside C's scope. Actuallyd.foo(5);
callsvoid foo(float)
and not theint
version.名称查找是重载解析的一个单独阶段。
首先进行名称查找。这是决定名称适用范围的过程。在这种情况下,我们必须决定
d.foo
是否表示dD::foo
、d.B1::foo
或d .B2::foo
。名称查找规则不考虑函数参数或任何东西;它纯粹是关于名称和范围。只有做出决定后,我们才会在找到名称的范围内对函数的不同重载执行重载解析。
在您的示例中,如果存在这样的函数,则调用
d.foo()
将找到D::foo()
。但没有。因此,在范围内向后工作,它会尝试基类。现在foo
可以同等地查找B1::foo
或B2::foo
因此它是不明确的。出于同样的原因,在
D
成员函数内调用不合格的foo(5);
会产生歧义。推荐解决方案的效果
是:创建名称
D::foo
,并使其标识两个函数。结果是d.foo
解析为dD::foo
,然后重载解析可能发生在由D::foo< 标识的这两个函数上/代码>。
注意:在此示例中,
D::foo(int)
和Base1::foo(int)
是同一个函数的两个标识符;但一般来说,对于名称查找和重载解析过程,它们是否是两个单独的函数并没有什么区别。Name lookup is a separate phase to overload resolution.
Name lookup occurs first. That is the process of deciding which scope the name applies to. In this case we must decide whether
d.foo
meansd.D::foo
, ord.B1::foo
, ord.B2::foo
. The name lookup rules do not take into account function parameters or anything; it is purely about names and scopes.Only once that decision has been made, do we then perform overload resolution on the different overloads of the function in the scope where the name was found.
In your example, calling
d.foo()
would findD::foo()
if there were such a function. But there is none. So, working backwards up the scopes, it tries the base classes. Nowfoo
could equally look up toB1::foo
orB2::foo
so it is ambiguous.For the same reason, you would get ambiguity calling unqualified
foo(5);
inside aD
member function.The effect of the recommended solution:
is that this creates the name
D::foo
, and makes it identify two functions. The result is thatd.foo
resolves tod.D::foo
, and then overload resolution can happen on these two functions that are identified byD::foo
.Note: In this example
D::foo(int)
andBase1::foo(int)
are two identifiers for the one function; but in general, for the name lookup and overload resolution process, it doesn't make a difference whether they are two separate functions or not.它对你有用吗?
Will it work for you?