1

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

#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()'

除了在 class 中声明 function 之外foo(),我没有做任何更改。然后突然出现了第一个程序中没有的冲突。我无法理解这一点。virtualFather

有什么建议么?谢谢你。

4

5 回答 5

3

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

于 2013-07-05T05:11:48.047 回答
2

请参考 按返回类型重载的函数? 关于为什么基于返回类型的重载/覆盖可能会出现问题。

于 2013-07-05T05:31:50.157 回答
1

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

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

例如,可以在此处找到参考资料。

于 2013-07-05T05:34:58.747 回答
1

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

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

那么它将Father::foo()被调用,而不是Son::foo()如果Father::foo()不是虚拟的。

由于Son::foo()不是覆盖Father::foo(),因此没有特殊要求返回类型匹配。但是,一旦您制作了Father::foo()virtual ,那么就会Son::foo()override Father::foo(),因此需要在返回类型中达成一致。

此外,当您有不同的参数类型而不是不同的返回类型时,就会发生重载。在同一个作用域中声明两个同名的函数,只是它们的返回类型不同,这是完全非法的。

于 2013-07-05T05:12:05.697 回答
0

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

于 2013-07-05T05:26:54.233 回答