试图弄清楚为什么在以下代码中没有引起过载歧义:
float foo2(float& i)
{
cout << "call from reference" << endl;
return i;
}
float foo2(float i)
{
cout << "call from non reference"<<endl;
return i;
}
int main()
{
cout<<foo2(2); // print "call from non reference"
}
调用参数未通过引用传递的foo2。为什么?如何调用传递引用参数的foo2?
答案 0 :(得分:6)
调用参数不的
foo2
被引用传递。为什么呢?
因为您无法通过引用传递非常量引用的函数来传递常量或任何计算表达式。要通过引用传递表达式,您需要一个可赋值 - 可以出现在赋值表达式左侧的值。由于2
不能出现在赋值表达式的左侧,因此它不能用于调用需要引用的函数。当引用为const
时,您可以传递任何内容,因为C ++将创建一个临时变量,为其分配表达式,并将引用传递给带有const
引用的函数。
如何调用传递参考参数的
foo2
?
没有明显的方法可以做到这一点,因为当您传递一个变量或另一个可以成为引用的表达式时,编译器会抱怨您正在进行模糊调用:
float f;
foo2(f); // <<== This will not compile
有一种方法可以调用它:你可以创建一个只匹配两个函数签名之一的函数指针,并用它来打电话:
typedef float (*fptr_with_ref)(float&);
int main()
{
cout<<foo2(2) << endl; // print "call from non reference"
fptr_with_ref foo2ptr(foo2); // Only one overload matches
float n = 10;
cout<<foo2ptr(n) << endl; // Calls foo2(float&)
}
答案 1 :(得分:3)
您作为2
的参数提供的foo2
是一个右值,它不能作为参考。因此,不能用它来调用接受引用的函数。
答案 2 :(得分:1)
您的问题是用C ++术语,而不是设计术语。 C ++以某种方式支持事物,因为它在设计方面是有意义的。 C ++允许你做很多事情,但是如果你想用它制作好的软件你就不能只遵循文字C ++规则,你需要更进一步。在实践中,这意味着你最终会制定自己的规则。
在你的情况下 - 好吧,如果我没有真正改变函数中的变量,我就永远不会制作参考变体。
如果你采用这样的规则&#39;对于你自己,然后你马上就会明白为什么ref函数没有绑定:首先,改变松散常数的重点是什么?
如果你制定了正确的规则,你会发现它们得到了C ++的精美支持。就像...函数更改一个对象:传递非const引用。没变? const ref。可选的? const指针。接管mem管理?非常量指针。
请注意,这只是一个开始,特别是在多线程发挥作用时。你必须在“合同”中添加内容。功能。 const ref的例子:对象必须保持“活着”状态。通话结束后?呼叫期间对象可以改变吗?等等。