[英]Usefulness of covariant return types in C++ clone idiom?
The usual clone idiom makes use of covariant return types: 通常的克隆习语使用协变返回类型:
struct Base {
virtual Base* clone();
};
struct Derived : public Base {
Derived* clone();
};
I've read things to the effect that covariant return types were a later addition to C++, and older compilers may not support them. 我已经读过这样的信息,即协变返回类型是C ++的后续添加,而较旧的编译器可能不支持它们。 In this case the
Derived
class must declare its clone
member function to return a Base*
. 在这种情况下,
Derived
类必须声明其clone
成员函数以返回Base*
。 Since, presumably, I'm only accessing Derived
objects through Base
pointers and/or references when using this idiom, what is the real use/benefit to declaring the return type Derived*
? 因为,大概我只是在使用这个习语时通过
Base
指针和/或引用来访问Derived
对象,声明返回类型Derived*
的真正用途/好处是什么?
Also, a related question: 另外,一个相关的问题:
I would prefer to use smart pointers to express transfer-of-ownership semantics for the clone
signature. 我更喜欢使用智能指针来表达
clone
签名的所有权转移语义。 This is not possible when using covariant return types, as auto_ptr<Derived>
is not covariant with auto_ptr<Base>
. 使用协变返回类型时,这是不可能的,因为
auto_ptr<Derived>
与auto_ptr<Base>
不协变。 (Please note that I'm not looking for a lecture on the use of smart pointers -- auto_ptr
is just used as an example here). (请注意,我不是在寻找关于智能指针使用的讲座 - 这里仅以
auto_ptr
为例)。 So in this case, is there any reason not to have Derived
return auto_ptr<Base>
? 那么在这种情况下,有没有理由不让
Derived
返回auto_ptr<Base>
? Is there a better way to express the transfer-of-ownership semantics? 是否有更好的方式来表达所有权转移语义?
Since, presumably, I'm only accessing Derived objects through Base pointers and/or references when using this idiom...
因为,据推测,我只是在使用这个成语时通过Base指针和/或引用来访问Derived对象...
You presume wrong. 你认为错了。 Just because a Base class exists doesn't mean you'll always be using it.
仅仅因为Base类存在并不意味着你将永远使用它。 If I have a
Shape
class with sub classes Circle
and Rectangle
, and I also have a Window
class. 如果我有一个带有子类
Circle
和Rectangle
的Shape
类,我也有一个Window
类。 I'm not going to use a Shape*
for a the window's position and size when I can just use Rectangle
. 当我可以使用
Rectangle
时,我不打算使用Shape*
作为窗口的位置和大小。
For the transfer-of-ownership, you shouldn't be using smart pointers anyway. 对于所有权转让,无论如何都不应该使用智能指针。 I know you don't want a lecture, but I'm not saying that smart pointers are bad, you just shouldn't be using them in
clone()
. 我知道你不想讲课,但我不是说智能指针很糟糕,你不应该在
clone()
使用它们。 You can't transfer ownership of something that has no ownership in the first place. 您不能首先转让没有所有权的东西的所有权。 If someone wants an
auto_ptr
then they should construct it with the cloned raw pointer. 如果有人想要一个
auto_ptr
那么他们应该用克隆的原始指针构造它。 Same goes for other smart pointer types. 其他智能指针类型也是如此。
It's useful when you have a pointer to Derived
and want to get a clone of it: 当你有一个指向
Derived
的指针并希望得到它的克隆时,它很有用:
Derived *ptr = ...;
Derived *clone = ptr->clone();
without covariant return types you must do an explicit cast: 如果没有协变返回类型,您必须进行显式转换:
Derived *clone2 = (Derived*)ptr->clone();
Note that Derived
may be a base class for even more derived classes, in that case it makes even more sense. 请注意,
Derived
可能是更多派生类的基类,在这种情况下它更有意义。
Unfortunately auto_ptr<Derived>
and auto_ptr<Base>
are not covariant. 不幸的是,
auto_ptr<Derived>
和auto_ptr<Base>
不协变。 So you must return the same type from all clone functions in that case. 因此,在这种情况下,您必须从所有克隆函数返回相同的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.