据我所知,要覆盖继承类中的虚拟函数,函数应具有与基类函数相同的返回值数据类型。
但是,如果您返回的指针或值属于从原始函数返回值的类继承的类,编译器将接受更改返回值,如下所示:
#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
关键字。