关于c ++:Polymorphism不能使用相同数据类型的函数返回值(Base和Inherited类)

Polymorphism is not working with function return values of same data type (Base and Inherited class)

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>

class Base{
public:
virtual  Base * clone() {
    std::cout <<"Base::clone()
"
;
    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()
"
;
    Derived * dp = new Derived ;
    return dp ;
}
  std::string ID() {return"Derived class";}
};


int main() {

  Base * bp = new Derived;

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

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

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

}

G++的输出是:

1
2
3
4
Derived::clone()
Base class
Derived::clone()
Derived class

overriden Derived类中的clone()函数返回指向堆上同一对象副本的指针。从输出来看,每次调用正确版本的clone(),但不调用ID()。为了解决这个问题,我不得不降低返回值以获得dynamic_cast所期望的效果,或者使virtual ID()成为基类。

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

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

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


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

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

如果要具有多态行为,请为这两个id()方法添加virtual关键字。如果你使用C++ 2011兼容编译器,你也可以在EDCOX1上添加EDCOX1 16关键字17。