简体   繁体   English

C ++ clone习语中协变返回类型的用处?

[英]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. 如果我有一个带有子类CircleRectangleShape类,我也有一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM