【问题标题】:C++ member functions with same name and parameters, different return typeC++ 成员函数具有相同的名称和参数,不同的返回类型
【发布时间】:2016-09-08 21:22:45
【问题描述】:

如果我在这样的类中定义具有相同名称和参数但返回类型不同的成员函数是否有效:

class Test {
public:
    int a;
    double b;
}

class Foo {    
private:
    Test t;
public:
    inline Test &getTest() {
        return t;
    }
    inline const Test &getTest() const {
        return t;
    }
}

如果我们有以下代码,会调用哪个成员函数?

Foo foo;  // suppose foo has been initialized
Test& t1 = foo.getTest();
const Test& t2 = foo.getTest();

【问题讨论】:

  • 你的函数没有相同的签名...

标签: c++


【解决方案1】:

不,它无效,但在您的示例中是有效的,因为最后一个const 实际上是签名的一部分(隐藏的Foo *this 第一个参数现在是const Foo *this) .

用于以只读方式访问(获取const引用,方法为常量),或写入(获取非const引用,方法为非常量)

当然,在这两种方法中返回同一实体(常量或非常量)的引用仍然是一个不错的设计选择!

【讨论】:

  • 也就是说最后一个const修改了隐式this参数的类型,所以可以认为是改变了函数的参数类型。
  • 是的,尽管它在普通 C++ 编码人员中不是很流行。太糟糕了。
【解决方案2】:

没有。

你不能重载返回类型。

为什么?标准是这样说的。

这实际上是有道理的——你无法确定在所有情况下都调用什么函数。

【讨论】:

    【解决方案3】:

    具有相同形参列表的 const 和非 const 方法可以并排出现,因为 this 指针被视为隐藏参数并且具有不同的类型。这可用于提供变异和非变异访问器,就像您问题中的代码一样。

    如果签名完全相同,则否。

    【讨论】:

      【解决方案4】:

      用一个例子扩展前面的答案和你给定的代码,这样你就可以知道什么时候被调用:

      #include <iostream>
      
      class Test {
      public:
          int a;
          double b;
      };
      
      class Foo {
      private:
          Test t;
      public:
          inline Test &getTest() {
              std::cout << "Non const-refrence " << std::endl;
              return t;
          }
          inline const Test &getTest() const {
              std::cout << "Const-refrence " << std::endl;
              return t;
          }
      };
      
      int main() {
          Foo foo;
          Test& t1 = foo.getTest();
          const Test& t2 = foo.getTest();
      
          const Foo bar;
          const Test& t3 = bar.getTest();
      
          return 0;
      }
      

      有输出:

      Non const-refrence
      Non const-refrence
      Const-refrence
      

      您在第二个 getTest 签名后看到的const 告诉编译器不会因为调用此函数而修改任何成员变量。

      【讨论】:

        【解决方案5】:

        如果我定义具有相同名称和参数但返回类型不同的成员函数 [...] 是否有效?

        没有。 既不是方法类也不是非类函数。

        原因是模棱两可。可能会出现编译器仅通过推导返回值无法选择正确的重载的情况。

        总结:你不能基于返回类型重载方法。


        在您的示例中,这两种方法:

         Test& getTest();
         const Test& getTest() const;
        

        正确重载是因为签名不同,但不是因为返回值不同!

        确实,函数签名由以下部分组成:

        • 函数名
        • cv 限定符
        • 参数类型
        • 方法限定符

        所以你的方法的签名是:

        1) getTest();
        2) getTest() const;
                      ^------ Note that const qualifiers of the method is part of signature
        

        如您所见,返回值不是签名的一部分,但方法限定符的const是。


        如果我们有以下代码,会调用哪个成员函数?

        使用以下代码:

        Foo foo;
        Test& t1 = foo.getTest();
        const Test& t2 = foo.getTest();
        

        它只会调用 no-const 方法甚至t2的情况下。

        原因是foo 对象在那个范围内是no-const,所以每个 方法将以非 const 形式调用。

        详细来说,在第三行:

        const Test& t2 = foo.getTest();
        

        foo.getTest() 将返回 no-const 引用,after 将 在 const 引用中隐式转换。

        如果您想强制编译器调用const 版本,您应该在const 中“临时转换”对象foo

        例如:

        const int& t2 = static_cast<const Foo&>(foo).getTest();
        

        在这种情况下,我会得到对象的 const 引用,因此该对象将被视为 const,并且将调用正确的 const 方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多