函数的模糊引用/值版本

时间:2011-05-02 12:49:11

标签: c++ overloading ambiguity

考虑以下函数原型:

void Remove(SomeContainer& Vec, const std::size_t Index);

SomeContainer Remove(SomeContainer Vec, const std::size_t Index);

第二个是第一个实现的。也就是说,它们在功能上都是相同的,除了一个是通过引用传递而另一个是按值传递。

然而,GCC说这些在这种情况下是模棱两可的,即使第一种形式是唯一一种不返回值的形式:

Remove(SomeContainer, 123);

是否有解决方法,或者我是否必须为每个表单提供不同的名称?

4 个答案:

答案 0 :(得分:5)

返回类型不是函数重载的基础 功能重载只能使用以下标准之一:

  1. 没有参数
  2. 参数类型&
  3. 参数序列
  4. 调用者可以忽略返回类型,因此它不是函数重载的有效标准。

    说完上面的内容,传递值并传递一个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)

传递引用/值不用于确定函数重载,因为编译器无法知道哪个是必需的 - 两者对于作为参数传递的值都是同样好的匹配。正如其他人所指出的,从不考虑返回类型。