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



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

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

#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

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

我的问题:为什么多态性在第一例中不起作用

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

因为clone()应该从Derived类返回一个指向Object的指针,因此Derived类的ID()函数而不是Base类,但在这种情况下,我有Base类的ID()函数?

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

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

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

最新更新