协变返回类型和类型转换
Covariant return type and type conversion
> 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.
尽管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) 返回的类型。[..]
在标准文本中,有一个相关的例子。
重点不是这样做:
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
- 基于返回类型的转换和过载扣除
- 用户定义的转换无法指定返回类型
- 创建一个函数来转换数组元素的类型并返回数组的地址
- 表达式到C++类类型转换器/类型转换
- C++函数模板:必须使用 & for 参数类型和返回类型?
- 从类型*转换为类型,反之亦然
- C++中的类型转换:相关类型和不相关类型
- 无法将类型转换为类型*-C++编译错误
- 重载参数类型和返回类型上的函数
- 类型转换为类型&&运算符
- 是否可以找出多态C++ 14 lambda 的参数类型和返回类型
- 为什么"Foo f(Bar());"可以是采用 Bar 类型并返回类型 Foo 的函数的声明?
- 无法从类型 x 转换为类型 x
- 返回类型与返回类型(运算符++)不相同,也不协变
- 无法从类型x转换为类型x
- 在VS2010中获取可调用类型的返回类型
- c不能从A*类型转换为B*类型
- 将JNI类型转换为c++类型
- 静态强制转换返回类型
- 这些形式之间有什么区别吗:返回类型与返回类型和?