覆盖具有不同返回类型的成员函数

时间:2012-01-23 04:49:21

标签: c++ virtual-functions override redefinition

考虑以下示例:

#include <iostream>

using namespace std;

class base
{
   public:
      virtual int func()
      {
         cout << "vfunc in base class\n";
         return 0;
      }
};

class derived: public base
{
   public:
      double func()
      {
         cout << "vfunc in derived class\n";
         return 0;
      }
};

int main()
{
   base *bptr = new derived;
   bptr->func();

   return 0;
}

编译器为上面的代码提供了一个错误,即覆盖函数存在冲突类型。为什么不能使用不同的返回类型覆盖派生类中的函数?

我相信,为了覆盖一个函数,需要在派生类中重新定义基类虚方法。要重新定义方法,方法的签名必须相同。由于返回类型不是签名的一部分,我相信即使返回类型有差异,该方法仍将被重新定义?在上述代码的情况下,虚拟函数func在派生类中重新定义,具有不同的返回类型。但是编译器会抛出错误。我的理解是否正确?

5 个答案:

答案 0 :(得分:25)

覆盖本质上意味着将在运行时调用Base类方法或Derived类方法,具体取决于指针指向的实际对象。
它意味着:
即:可以通过调用Derived类方法替换可以调用Base类方法的每个地方,而无需更改调用代码。

为了实现这一点,唯一可能的方法是限制重写虚方法的返回类型以返回与Base类相同的类型或从该类派生的类型(共变量返回类型),并且标准强制执行此操作条件。

如果上述条件不存在,它会留下一个窗口,通过添加新功能来破坏现有代码。

答案 1 :(得分:10)

为了覆盖虚函数,返回值必须完全相同*。 C ++将doubleint之间自动转换 - 毕竟,从派生类指针调用时,它将如何知道您想要的返回类型?请注意,如果您更改部分签名(参数,常量等),那么您也可以更改返回值。

* - 严格来说,它必须是'协变'。这意味着您返回的类型必须是父函数返回类型的子集。例如,如果父类返回base *,则可以返回derived *。由于derived s同时也是base s,因此编译器允许您以这种方式覆盖。但是,您无法返回完全不相关的类型,例如intdouble;只是因为隐式转换并不意味着编译器会让你做这种覆盖。

答案 2 :(得分:6)

this question。总而言之,如果类型为covariant,则只能使用不同的返回类型覆盖虚函数。

答案 3 :(得分:2)

如果要覆盖,则应尝试使用模板。

请参阅以下内容:

#include <iostream>

using namespace std;

class base
{
   public:
      template<typename X> X func()
      {
         cout << "vfunc in base class\n";
         return static_cast<X>(0);
      }  
};    

class derived: public base
{
   public:
      template<typename X> X func()
      {
         cout << "vfunc in derived class\n";
         return static_cast<X>(2);
      }  
};    

int main()
{
   derived *bptr = new derived;
   cout << bptr->func<int>() << endl;
   cout << dynamic_cast<base*>(bptr)->func<int>() << endl;

   derived *bptr2 = new derived;
   cout << bptr->func<double>() << endl;
   cout << dynamic_cast<base*>(bptr)->func<int>() << endl;


   return 0;
}

当然,你不需要在两个不同的类中声明它,你可以这样做:

class base
{
   public:
      int func()
      {
         cout << "vfunc in base class\n";
         return 0;
      }  

      double func(){
        cout << "vfunc for double class\n";
        return 2.;

      }
};

答案 4 :(得分:0)

覆盖是不可能的,因为签名是不同的。覆盖的基本目的是多态,但在上面的例子中是不可能的

相关问题