【问题标题】:function overriding with different return types具有不同返回类型的函数覆盖
【发布时间】:2013-02-25 09:55:07
【问题描述】:

返回类型对函数重写有影响吗? (据我所知,返回类型不是函数/方法签名的一部分) 在一个基类中,我有一个没有参数的函数,它返回int 并且是纯虚拟的。在每个派生类中,我为返回类型定义了一个枚举。该函数在派生类中被覆盖,即它具有相同的签名但不同的行为。 问题是:重写和返回类型不是函数重写的一部分是否合法?

代码示例:

class Base
{
  public:
  typedef int ret;
  virtual ret method() = 0;
};

class Der1
{
public:
  enum ret1{
    ret1_0,
    ret1_1
  };
  ret1 method() { return ret1_1;}
};

class Der1
{
public:
  enum ret2{
    ret2_0,
    ret2_1
  };
  ret1 method() { return ret2_0;}
};

【问题讨论】:

  • @LihO - 谢谢你的留言。这是一个错字

标签: c++ overriding return-type


【解决方案1】:

您可以覆盖具有不同返回类型的函数,但只允许协变返回类型

函数覆盖意味着在运行时将调用基类方法或派生类方法,具体取决于指针所指向的实际对象。
这意味着:
即:可以调用基类方法的每个地方都可以通过调用派生类方法来替换,而无需更改调用代码。

为了实现这一点,唯一可能的方法是限制覆盖虚拟方法的返回类型,使其返回与基类相同的类型或派生自基类的类型(协变返回类型),因此标准强制执行这种情况。

如果没有这种情况,现有代码将因添加新功能(新的覆盖函数)而中断。

【讨论】:

  • 您的协变链接已损坏
【解决方案2】:

简短回答:不,这是不允许的,或者更好地说它不是覆盖而是覆盖,即您没有覆盖Base::method(),而是创建一个具有相同名称的新方法。大多数编译器都会警告你。使用您的示例代码,但假设 Base::method不是纯虚拟的,请考虑:

void callMethod(Base const& b)
{
  auto a1 = b.method();  //what should the type of a1 be? -> it's int. Every time.
  std::cout << a1 << '\n';
}

int main()
{
  Der1 d1;
  auto a2 = d1.method(); //a2 is ret1_1 of type ret1
  callMethod(d1);        //calls Base::method and prints that int, not Der1::method
}

你说得对,返回类型不是函数签名的一部分。但是当覆盖虚函数时,签名并不是最重要的。 §10.3,7 明确指出:

重写函数的返回类型应与 被覆盖函数或 协变 的返回类型 函数的类。如果函数 D::f 覆盖了函数 B::f,函数的返回类型是协变的,如果它们满足 以下标准:

——都是指向类的指针,都是 对类的左值引用,或者两者都是对类的右值引用 类

——B::f的返回类型中的类是同一个类 D::f 的返回类型中的类,或者是一个明确且 返回中类的可访问的直接或间接基类 D::f的类型

——指针或引用都相同 cv-qualification 和 D::f 返回类型中的类类型具有 与类类型相同或更少的 cv 限定 在B::f的返回类型中。

【讨论】:

    【解决方案3】:

    你所拥有的不是覆盖。

    c++ 支持原始指针和原始引用的协变返回类型。

    仅此而已。

    【讨论】:

      【解决方案4】:

      我们不应该通过覆盖来改变基类中函数的返回类型。不建议通过隐藏基成员来更改返回类型,因为这会导致无法以多态方式使用的奇怪东西。

      【讨论】:

        猜你喜欢
        • 2012-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多