使用相同的参数和不同的返回类型重载虚函数

时间:2013-07-05 05:08:48

标签: c++

我有以下代码编译时没有任何错误或警告。

#include<iostream>

using namespace std;

class Father
{
   public:
   int foo()
   {
       cout<<"int foo";
       return 111;
   }
};
class Son: public Father
{
   public:
   long foo()
   {
       cout<<"long foo";
       return 222;
   }
};

int main()
{
  Son x;
  long n;
  n=x.foo();
  cout<<"\nn is "<<n;
  return 0;
}

输出如下所示。

long foo
n is 222

我认为函数foo()在派生类Son中被覆盖,并且没有重载,因为以下程序给了我错误。

using namespace std;

class Father
{
   public:
   int foo()
   {
       cout<<"int foo";
       return 111;
   }
   long foo()
   {
       cout<<"long foo";
       return 222;
   }
};


int main()
{
  Father x;
  long n;
  n=x.foo();
  cout<<"\nn is "<<n;
}

错误信息如下所示。

error: 'long int Father::foo()' cannot be overloaded
error: with 'int Father::foo()'

两个结果都是预期的,因为当两个函数仅由返回类型不同时,则覆盖发生而不是重载。但是当我在第一个程序中将函数foo()声明为virtual时,我收到错误,我无法理解其中的原因。我违反了什么规则?该计划如下所示,

#include<iostream>

using namespace std;

class Father
{
   public:
   virtual int foo()
   {
       cout<<"int foo";
       return 111;
   }
};
class Son: public Father
{
   public:
   long foo()
   {
       cout<<"long foo";
       return 222;
   }
};


int main()
{
  Son x;
  long n;
  n=x.foo();
  cout<<"\nn is "<<n;
}

错误信息如下所示,

error: conflicting return type specified for 'virtual long int Son::foo()'
error:   overriding 'virtual int Father::foo()'

除了在课程foo()中将virtual声明为Father之外,我没有做任何更改。然后突然出现了第一个程序中缺席的冲突。我无法理解这一点。

有什么建议吗?谢谢。

5 个答案:

答案 0 :(得分:3)

您不能通过更改返回类型来重载,只需更改函数的参数类型/数量(或添加const修饰符,以及可能的其他一些方法)。它在派生类中进行编译的原因是因为派生的类基本上隐藏了基类中的那个。

答案 1 :(得分:2)

请参阅 Function overloading by return type? 关于为什么基于重载/覆盖的返回类型可能会有问题。

答案 2 :(得分:1)

当成员函数不是虚函数时,派生类中具有相同名称的函数不会覆盖基类中的函数,至少不是通常意义上的函数。派生类函数仅隐藏基类函数。例如,如果你有这样的代码:

Son s;
Father &f = s;
f.foo();

如果Father::foo()不是虚拟的,则会调用Son::foo(),而不是Father::foo()

由于Son::foo()未覆盖Father::foo(),因此没有特殊要求返回类型匹配。但是,如果您将Father::foo()设为虚拟,那么Son::foo()会覆盖Father::foo(),因此需要在返回类型中达成协议。

此外,当您有不同的参数类型而不是不同的返回类型时,会发生重载。在同一范围内声明具有相同名称的两个函数,只是它们的返回类型不同,这是完全违法的。

答案 3 :(得分:1)

返回tipe与基类不同的虚函数和派生的函数是标准允许的,并且被命名为协变函数。

但是,某些约束适用于返回类型。基本上,如果它返回指针或对类的引用,则允许定义协变函数;在这种情况下,基类必须返回一个指针或对其子类返回的类的直接或间接祖先的引用。

可以找到参考文献,例如here

答案 4 :(得分:0)

第一个示例程序采用了覆盖的概念,因为在派生类中定义的函数被调用。在虚拟示例程序中,如果函数在基类中被声明为虚函数,那么函数在派生类需要与基类虚函数具有相同的签名。在这种情况下,派生类中函数的类型是不同的,因为它给出了错误。