【问题标题】:C++ function overloading resolution involving pass-by-value, reference and constant reference涉及传值、引用和常量引用的 C++ 函数重载解析
【发布时间】:2016-04-20 12:28:52
【问题描述】:

假设我在 C++ 中使用以下 3 个签名定义了一些函数 f

void f(int x) {}
void f(int& x) {}
void f(const int& x) {}

这些函数可以共存,因为它们的参数类型不同。

现在我运行以下代码:

int main {
   int i = 3;
   const int ci = 4;

   f(3);
   f(i);
   f(ci);
}

C++ 如何知道在这种特定情况下要调用哪个重载函数?在 C++ 中编写重载函数以避免歧义的一般规则是什么(最佳实践?)。当前的 C++14 标准是否指定了任何特定规则?

【问题讨论】:

  • “在 C++ 中编写重载函数以避免歧义的一般规则是什么” 最好的规则是不要重载,除非它直观地对人类读者完全有意义。
  • 我怀疑您是否实际测试过编译具有这些声明的代码。由于不明确的调用,至少 clang++ 和 g++ 都会出错。

标签: c++ overloading


【解决方案1】:

这三个调用都是不明确的,所以程序不会编译。

f(3);

这可以使用第一个或第三个重载。它们同样出色,所以调用是模棱两可的。

f(i);

这可以使用第一个、第二个或第三个重载。第二个优于第三个;在可能的情况下,绑定到int& 比绑定到const int& 更受欢迎。因此,以这种方式重载 cv-qualification 是可以的。但是第一个和第二个重载之间存在歧义。

f(ci);

这可以使用第一个或第三个重载。同样,它们同样好,所以调用是模棱两可的。


该标准精确地规定了重载决议的规则。它们非常复杂,因此以一种使读者难以判断将调用哪个重载的方式重载函数是一个坏主意。你可以找到规则here

【讨论】:

    【解决方案2】:

    你不能超载:

    void f(int x) {}
    void f(const int& x) {}
    

    鉴于这些,编译器将无法消除以下调用的歧义:

    f(10);
    

    你不能超载:

    void f(int x) {}
    void f(int& x) {}
    

    鉴于这些,编译器将无法消除以下调用的歧义:

    int i = 0;
    f(i);
    

    你可以重载:

    void f(int& x) {}
    void f(int const& x) {}
    

    鉴于这些,您可以使用:

    int i = 0;
    f(i);    // Resolves to f(int&)
    f(10);   // Resolves to f(int const&)
    

    【讨论】:

      【解决方案3】:

      void f(int x) {} 该函数将拥有对象的副本,它是临时的,所以如果您想修改值或传递大量数据,请不要使用它。

      void f(int& x) {} 相同但通过引用传递,因此它是来自 c 的指针,但您可以像使用普通对象一样使用它。您将能够对其进行修改,并且最好传递大量数据,因为编译器没有太多复制它。

      void f(const int& x) {} const 在参数前表示对象不能被修改。顺便说一句,您不必在 main 中将其声明为 const。

      我不确定函数调用案例部分,所以我不会回答;)

      【讨论】:

      • 在问题中假设这些可以共存。它们没有,因为编译器无法区分它们,因为在所有三种情况下,参数类型基本上都是int x
      • @J.J.Hakala 他们当然可以共存。它们甚至可以通过转换为函数指针来手动选择重载来单独调用。
      • @Brian 我没有想到函数指针,当然可以得到每个函数的函数指针。我想我应该以不同的方式表达我的评论,例如“如果希望像问题中那样直接调用 f(),那么这三个函数定义不能共存。”
      猜你喜欢
      • 1970-01-01
      • 2013-07-31
      • 2011-07-24
      • 1970-01-01
      • 2016-05-25
      • 1970-01-01
      相关资源
      最近更新 更多