协变return类型和类型转换
Covariant return type and type conversion
s->duplicate()
return 类型为 Box*
的对象,但我在使用 Box*
初始化它时遇到错误。看起来它正在转换回 Shape*
。如果将协变 return 类型转换回基础 class 指针,那么它有什么意义?:
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* b = s->duplicate();
这显然行不通,因为 Shape::duplicate()
returns 和 Shape*
。相反,如果您直接在 Box
上调用 duplicate()
,则要接受 Box*
:
Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Box
尽管 Box::duplicate
是 在运行时调用(通过虚拟分派),尽管 Box::duplicate
确实 覆盖 Shape::duplicate
(协变),虽然 Box::duplicate
做 return 一个 Box*
,你仍然会得到一个 Shape*
指针,因为你是通过Shape*
指针调用duplicate()
,而Shape*
是Shape::duplicate()
的return类型,编译器只会看到你调用Shape::duplicate
,不是 Box::duplicate
.
C++ 不能动态地 select 类型,所以这是它能做的最好的。您的 Box*
正在从 Box::duplicate
中自动转换为 Shape*
。正如巴里所说,"it still has to compile at compile time, and at compile time all we know is that it returns a Shape*
".
然后,要再次将其变成 Box*
,您需要显式转换它(使用 static_cast
或 dynamic_cast
),因为不存在隐式向下转换。
[C++11: 10.3/7]:
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. [..]
[C++11: 10.3/8]:
If the return type of D::f
differs from the return type of B::f
, the class type in the return type of D::f
shall
be complete at the point of declaration of D::f
or shall be the class type D
. When the overriding function is called as the final overrider of the overridden function, its result is converted to the type returned by the (statically chosen) overridden function (5.2.2). [..]
在标准文本中,有一个相关示例。
s->duplicate()
return 类型为 Box*
的对象,但我在使用 Box*
初始化它时遇到错误。看起来它正在转换回 Shape*
。如果将协变 return 类型转换回基础 class 指针,那么它有什么意义?:
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* b = s->duplicate();
这显然行不通,因为 Shape::duplicate()
returns 和 Shape*
。相反,如果您直接在 Box
上调用 duplicate()
,则要接受 Box*
:
Box* old = new Box;
Box* b = old->duplicate(); // OK! We know it's a Box
尽管 Box::duplicate
是 在运行时调用(通过虚拟分派),尽管 Box::duplicate
确实 覆盖 Shape::duplicate
(协变),虽然 Box::duplicate
做 return 一个 Box*
,你仍然会得到一个 Shape*
指针,因为你是通过Shape*
指针调用duplicate()
,而Shape*
是Shape::duplicate()
的return类型,编译器只会看到你调用Shape::duplicate
,不是 Box::duplicate
.
C++ 不能动态地 select 类型,所以这是它能做的最好的。您的 Box*
正在从 Box::duplicate
中自动转换为 Shape*
。正如巴里所说,"it still has to compile at compile time, and at compile time all we know is that it returns a Shape*
".
然后,要再次将其变成 Box*
,您需要显式转换它(使用 static_cast
或 dynamic_cast
),因为不存在隐式向下转换。
[C++11: 10.3/7]:
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. [..]
[C++11: 10.3/8]:
If the return type ofD::f
differs from the return type ofB::f
, the class type in the return type ofD::f
shall be complete at the point of declaration ofD::f
or shall be the class typeD
. When the overriding function is called as the final overrider of the overridden function, its result is converted to the type returned by the (statically chosen) overridden function (5.2.2). [..]
在标准文本中,有一个相关示例。