C++ 重载具有相同参数和不同返回类型的虚拟函数

C++ 重载具有相同参数和不同返回类型的虚拟函数,c++,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

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

#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;
}
我假设函数
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;
}
这两种结果都符合预期,因为当两个函数仅在返回类型上不同时,就会发生重写而不是重载。但是,当我在第一个程序中将函数
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()'
除了在类
Father
中将函数
foo()
声明为
virtual
之外,我没有做任何更改。然后突然出现了第一个程序中没有的冲突。我无法理解这一点


有什么建议吗?谢谢。

只有通过更改函数的参数类型/数量(或添加常量修饰符,可能还有其他一些方法),才能通过更改返回类型来重载。当您在派生类中执行此操作时,它会编译的原因是,派生类本质上对基类隐藏了它。

您不能通过更改返回类型来重载,而只能通过更改函数的参数类型/数量(或添加常量修饰符,以及可能的其他一些方式)。当您在派生类中执行此操作时,它会编译的原因是,派生类本质上会对基类隐藏该函数。

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

Son s;
Father &f = s;
f.foo();
如果
Father::foo()
不是虚拟的,那么将调用的是
Father::foo()
,而不是
Son::foo()

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


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

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

Son s;
Father &f = s;
f.foo();
如果
Father::foo()
不是虚拟的,那么将调用的是
Father::foo()
,而不是
Son::foo()

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


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

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

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

请参阅 关于基于返回类型的重载/重写可能有问题的原因。

请参阅
关于基于返回类型的重载/重写可能有问题的原因。

返回类型不同于基类和派生类的虚拟函数是标准允许的,它们被命名为协变函数

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


例如,可以找到引用。

返回tipe不同于基类的虚拟函数,标准中允许使用派生函数,并将其命名为协变函数

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

例如,可以找到引用。

我假设函数foo()在派生类Son中被重写,而不是重载,因为下面的程序给了我错误。没有
虚拟
,因此它不会被覆盖。基类1是隐藏/阴影的。如果您使用父::fo
,我会认为同样的错误也会出现
Son s;
Father &f = s;
f.foo();