传递参考/值过载



试图弄清楚为什么在以下代码中没有引起重载歧义:

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?

调用其参数而非通过引用传递的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&)
}

演示。

您作为foo2的参数给出的2是一个右值,它不能是引用。因此,接受引用的函数不能用它来调用。

您的问题是用C++术语提出的,而不是用设计术语提出的。C++在某种程度上支持事物,因为它在设计方面是有意义的。C++允许你做很多事情,但如果你想用它制作出好的软件,你就不能仅仅拘泥于字面上的C++规则,你需要更进一步。在实践中,这意味着你最终会制定自己的规则。

在您的情况下,如果我没有实际更改函数中的变量,那么我永远不会生成引用变量。

如果你自己采用这样的"规则",那么你会立刻明白ref函数为什么不绑定:首先,改变一个松散的常数有什么意义?

如果你制定了正确的规则,你会发现它们得到了C++的完美支持。喜欢函数更改对象:传递非常数引用。没有更改吗?const ref可选?const指针。接管mem管理?非常量指针。

请注意,这只是一个开始,尤其是当多线程开始发挥作用时。你必须在函数的"契约"中添加一些东西。const-ref的示例:调用后对象是否必须保持"活动"状态?通话过程中对象是否会发生变化?等等

最新更新