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.
答案 0 :(得分:9)
虽然Box::duplicate
是在运行时调用(通过虚拟调度),虽然Box::duplicate
覆盖Shape::duplicate
(同上) ),虽然Box::duplicate
确实返回Box*
,但您仍然会获得Shape*
指针,因为您正在通过duplicate()
调用Shape*
Shape*
指针,Shape::duplicate()
是Shape::duplicate
的返回类型,编译器只会看到您调用Box::duplicate
,而不是Box*
。
C ++无法动态选择类型,所以这是它能做的最好的。在Shape*
的路上,您的Box::duplicate
会自动转换为Shape*
。正如Barry所说,"它仍然需要在编译时进行编译,在编译时我们所知道的是它返回Box*
"。
然后,要再次将其设为static_cast
,您需要明确地投射它(使用dynamic_cast
或[C++11: 10.3/7]:
),因为不存在隐式下转换。
[C++11: 10.3/8]:
重写函数的返回类型要么与被覆盖函数的返回类型相同,要么与函数类的协变相同。 [..]
D::f
如果B::f
的返回类型与D::f
的返回类型不同,则返回类型D::f
中的类类型应为 在声明D
时完成,或者是$(document).ready(function() { $('body').on('mouseover', 'li', function() { $("#vid").hide(); }); });
类。 当覆盖函数被调用为被覆盖函数的最终覆盖时,其结果将转换为(静态选择的)覆盖函数(5.2.2)返回的类型。 [..]
在标准文本中,有一个相关的例子。
答案 1 :(得分:5)
关键是不要这样做:
Box* b = s->duplicate();
由于Shape::duplicate()
返回Shape*
,显然无效。相反,如果您直接在Box*
致电duplicate()
,则接受Box
:
Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Box