c-多态不能与相同数据类型(基类和继承的类)的函数返回值一起使用

据我所知,要在继承的类中重写虚拟函数,该函数应具有与基类函数相同的返回值数据类型.

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

#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获得所需的效果,或者在基类中创建虚拟ID().

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

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

作为clone()应该返回一个指向派生类的对象的指针,因此派生类的ID()函数不是基类,但是在这种情况下,我具有基类的ID()函数?

解决方法:

在这种情况下,多态性可以正常工作.当您期望派生类时,代码打印基类的原因是因为ID()方法不是虚拟的.

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

如果要具有多态行为,请为两个ID()方法添加虚拟关键字.如果使用兼容C 2011的编译器,则还可以在Derived :: ID()上添加override关键字.

上一篇:C中的多态性


下一篇:C的多态性与boost scoped_ptr