5

返回类型是否影响函数覆盖?(据我所知,返回类型不是函数/方法签名的一部分)在基类中,我有一个函数,它不获取参数,返回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;}
};
4

4 回答 4

5

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

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

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

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

于 2013-02-25T09:58:26.470 回答
4

简短的回答:不,这是不允许的,或者最好说它不是覆盖而是覆盖,即您不是覆盖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

— both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

于 2013-02-25T10:04:15.070 回答
1

你所拥有的不是覆盖。

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

但仅此而已。

于 2013-02-25T10:00:58.267 回答
1

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

于 2013-02-25T10:03:11.323 回答