s->duplicate()返回一个Box*类型的对象,但是我得到了一个用Box*初始化它的错误。看起来它正在被转换回Shape*。如果将协变量返回类型转换回基类指针,有什么意义?:
struct Shape
{
virtual Shape* duplicate()
{
return new Shape;
}
};
struct Box : Shape
{
virtual Box* duplicate()
{
return new Box;
}
};
int main()
{
Shape* s = new Box;
Box* b = s->duplicate();
}错误:
main.cpp:22:12: error: cannot initialize a variable of type 'Box *' with an rvalue of type 'Shape *'
Box* b = s->duplicate();
^ ~~~~~~~~~~~~~~
1 error generated.发布于 2015-05-09 20:44:31
虽然Box::duplicate在运行时被调用(通过虚拟调度),尽管Box::duplicate确实覆盖Shape::duplicate (共变),尽管Box::duplicate确实返回Box*,但是仍然会得到一个Shape*指针,因为您通过Shape*指针调用duplicate(),而Shape*是Shape::duplicate()的返回类型,编译器只看到您调用Shape::duplicate,而不是Box::duplicate。
C++不能动态地选择类型,所以这是它所能做的最好的。您的Box*将在退出Box::duplicate时自动转换为Shape*。正如Barry所说,“它仍然必须在编译时编译,在编译时我们只知道它返回一个Shape*”。
然后,要再次将其转换为Box*,您需要显式地转换它(使用static_cast或dynamic_cast),因为不存在隐式向下转换。
[C++11: 10.3/7]:重写函数的返回类型应该是,或者与重写函数的返回类型相同,或者与函数类的协变量相同。。。[C++11: 10.3/8]:如果D::f的返回类型与B::f的返回类型不同,则返回类型D::f中的类类型应在D::f声明点完成,或者为类类型D。当重写函数被调用为被重写函数的最后一个覆盖项时,其结果将转换为(静态选择的)重写函数 (5.2.2)返回的类型。。。
在标准文本中,下面是一个相关的示例。
发布于 2015-01-25 03:28:31
重点不在于这样做:
Box* b = s->duplicate();这显然不能工作,因为Shape::duplicate()返回一个Shape*。相反,如果要在Box*上直接调用duplicate(),则需要接受Box:
Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Boxhttps://stackoverflow.com/questions/28132869
复制相似问题