考虑以下函数原型:
void Remove(SomeContainer& Vec, const std::size_t Index);
SomeContainer Remove(SomeContainer Vec, const std::size_t Index);
第二个是第一个实现的。也就是说,它们在功能上都是相同的,除了一个是通过引用传递而另一个是按值传递。
然而,GCC说这些在这种情况下是模棱两可的,即使第一种形式是唯一一种不返回值的形式:
Remove(SomeContainer, 123);
是否有解决方法,或者我是否必须为每个表单提供不同的名称?
答案 0 :(得分:5)
返回类型不是函数重载的基础 功能重载只能使用以下标准之一:
调用者可以忽略返回类型,因此它不是函数重载的有效标准。
说完上面的内容,传递值并传递一个Reference会给编译器带来歧义。例如:
void doSomething(int i)
{
}
void doSomething(int &i)
{
}
int main()
{
int val = 10;
doSomething(val); //Ambiguous
}
此处编译器无法确定将val
传递给doSomething()
的哪个版本。它可以对任何版本进行有效的函数调用,因此它在编译时请求帮助(因为这是静态链接)并将调用标记为不明确。
如果是你的话。重命名函数或传递指针参数是一个选择/首选项,这将使两个函数重载(同名但不同的参数类型)。但是,重要的是要考虑到要求&功能在选择首选项时要执行的操作。就个人而言,我不会为了超载而选择指针。如果我确实需要重新设置或使我的参数指向不同的变量,那么选择指针参数是有意义的。
简单的方法是只有两个不同的函数名称。没有任何开销,它与任何其他函数调用一样有效。
答案 1 :(得分:3)
如上所述,返回类型不考虑重载。但是,编译器 会考虑普通值并引用不同的类型,但通常不知道要调用哪个版本。换句话说,有两个重载函数只是在参数是值传递还是按引用传递时是不同的,直到你试图调用它为止:潜在的歧义在C ++中不是错误。
示例:
void f(int) {
cout << "value\n";
}
void f(int&) {
cout << "reference\n";
}
int main() {
int val = 42;
f(val); // Error! Ambiguous.
f(static_cast<int>(val)); // OK: The type is int. Will print "value"
}
我不知道如何发出你想要f(int&)
的信号,所以这里没有太多实际用处 - 我只是想弄清楚C ++重载是如何工作的。
答案 2 :(得分:2)
通过选择更多有区别的名称,您可以帮助编译器以及功能的用户:
Container Removed( const Container& c, size_t index );
void Remove( Container& c, size_t index );
将const
添加到不可变版本也会阻止用户意外调用命令式变体(编译器不允许这样做,至少不允许const
容器)。
答案 3 :(得分:1)
传递引用/值不用于确定函数重载,因为编译器无法知道哪个是必需的 - 两者对于作为参数传递的值都是同样好的匹配。正如其他人所指出的,从不考虑返回类型。