多态性不适用于相同数据类型的函数返回值(Base和Inherited类)

时间:2015-03-21 03:50:21

标签: c++ inheritance polymorphism

据我所知,在继承的类中覆盖虚函数,该函数应该具有与基类函数相同的返回值数据类型。

但是如果返回属于从原始函数的返回值的类继承的类的指针或值,编译器将接受更改返回值,如下所示:

#include <iostream>

class Base{
public:
virtual  Base * clone() {
    std::cout << "Base::clone()\n" ;
    Base * bp = new Base ;
    return bp ;
}
  std::string ID() {return "Base class";}
};

class Derived: public Base {
public:
  //Derived* and Base* are same data type (acceptable):
  Derived * clone() {
    std::cout << "Derived::clone()\n" ;
    Derived * dp = new Derived ;
    return dp ;
}
  std::string ID() {return "Derived class";}
};


int main() {

  Base * bp = new Derived;

  std::cout << bp->clone()->ID() <<"\n";

  std::cout << dynamic_cast <Derived*>(bp->clone())->ID() <<"\n";
  /*
  next code give error: cannot convert Base* to Derived*: 

  Derived * dp2 = bp->clone();
  std::cout << dp2->ID() << "\n";
  */
}

g ++的输出是:

Derived::clone()
Base class
Derived::clone()
Derived class

clone()类中的Overriden Derived函数返回指向堆上同一对象副本的指针。从输出中可以看出,clone()的正确版本每次都被调用,而不是ID()。为了解决这个问题,我不得不向下转换返回值以通过dynamic_cast获得所需的效果,或者在基类中生成virtual ID()

我的问题:为什么多态在第一种情况下不起作用

  std::cout << bp->clone()->ID() <<"\n";

因为clone()应该从Derived类返回指向对象的指针,因此ID()类的Derived函数不是Base类,而是在此case我有ID()类的Base函数?

1 个答案:

答案 0 :(得分:2)

在这种情况下,多态性正常工作。您希望Base class时代码打印Derived class的原因是因为ID()方法不是virtual

为了理解发生了什么,你必须像编译器一样查看代码。在您的示例中,bp是指向Derived实例的指针,但在代码中已将其键入为Base *,因此编译器会看到Base *。当编译器稍后在代码中看到bp->clone()时,它知道clone()类的Base方法返回Base *。最后,当编译器到达->ID()方法调用时,它会查看Base类定义并看到非虚拟方法,因此它确保在运行时{{1}在该位置调用方法。

如果您想要具有多态行为,请为两个ID()方法添加Base::ID()关键字。如果您使用符合C ++ 2011的编译器,还可以在virtual上添加override关键字。