[英]Function Overloading Based on Value vs. Const Reference
是否声明如下内容
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
有道理吗? 调用者如何区分它们? 我试过了
foo(9); // Compiler complains ambiguous call.
int x = 9;
foo(x); // Also ambiguous.
const int &y = x;
foo(y); // Also ambiguous.
目的似乎是区分具有临时性(即9
)和“常规”参数传递的调用。 第一种情况可能允许函数实现采用优化,因为很明显参数将在之后处理(这对于整数文字绝对没有意义,但对于用户定义的对象可能有意义)。
但是,当前的 C++ 语言标准没有提供专门针对参数的“l/r 值”重载的方法 - 作为参数传递给函数的任何 l 值都可以隐式转换为引用,因此歧义是不可避免。
C++11 引入了一个类似目的的新工具——使用r-value 引用,你可以重载如下
void foo(int x) { ... }
void foo(const int &&x) { ... }
...和foo(4)
(作为参数传递的临时 r 值)将导致编译器在int i = 2; foo(i)
时选择第二个重载int i = 2; foo(i)
int i = 2; foo(i)
会选择第一个。
(注意:即使使用新工具链,也无法区分示例中的案例 2 和案例 3!)
你可以用一个模板来做到这一点:
template<typename T> void foo(T x) { ... }
然后你可以通过值或引用调用这个模板:
int x = 123;
foo<int>(x); // by value
foo<int const&>(x); // by refernce
调用者如何区分它们?
在这种情况下无法区分。 无论是过载功能有相同的类型的基本数据类型作为参数。 并且通过引用并不计入不同的类型。
您可以使用static_cast
显式选择要调用的重载:
#include <iostream>
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
int main()
{
int x = 0;
auto f1 = static_cast< void(*)(int) >(foo);
f1(x);
auto f2 = static_cast< void(*)(const int&) >(foo);
f2(x);
}
但是,您应该先问问自己为什么要提供这两个重载。 要么您可以复制,要么不能。 两者同时? 为什么? 还使得调用者必须明确选择重载,这违背了函数重载的目的。 如果你真的想要考虑提供两个函数:
void foo_copying(int x) { std::cout << "foo(int)" << std::endl; }
void foo_non_copying(const int &x) { std::cout << "foo(const int &)" << std::endl; }
不是在 C++ 中。 Erlang 和 Haskell 等函数式语言通过允许您根据参数值指定函数重载而更加接近,但包括 C++ 在内的大多数命令式语言都需要基于方法签名的重载; 即每个参数的数量和类型以及返回值的类型。
签名中的const
关键字定义的不是参数的类型,而是它在函数内的可变性; 如果被函数修改或通过引用传递给任何不使用const
函数,“ const
”参数将产生编译器错误。
编译器不能。 foo 的两个定义都可以用于 int 的所有“变体”。
在第一个 foo 中,制作了 int 的副本。 复制 int 总是可能的。
在第二个 foo 中,传递了对 const int 的引用。 由于任何 int 都可以转换为 const int,因此也可以传递对它的引用。
由于这两种变体在所有情况下都有效,因此编译器无法选择。
如果您使用以下定义,事情就会变得不同:
void foo (int &x);
现在用foo(9)
调用它将采用第一种选择,因为您不能将 9 作为非常量 int 引用传递。
另一个例子,如果你用一个复制构造函数是私有的类来替换 int ,那么调用者就不能复制这个值,第一个 foo 变体将不会被使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.