开发者

Usefulness of covariant return types in C++ clone idiom?

开发者 https://www.devze.com 2023-01-25 05:00 出处:网络
The usual clone idiom makes use of covariant return types: struct Base { virtual Base* clone(); }; struct Derived : public Base {

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 effe开发者_StackOverflowct that covariant return types were a later addition to C++, and older compilers may not support them. In this case the Derived class must declare its clone member function to return a 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*?

Also, a related question:

I would prefer to use smart pointers to express transfer-of-ownership semantics for the clone signature. This is not possible when using covariant return types, as auto_ptr<Derived> is not covariant with 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). So in this case, is there any reason not to have Derived return 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...

You presume wrong. Just because a Base class exists doesn't mean you'll always be using it. If I have a Shape class with sub classes Circle and Rectangle, and I also have a Window class. I'm not going to use a Shape* for a the window's position and size when I can just use Rectangle.

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(). 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. 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 *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.

Unfortunately auto_ptr<Derived> and auto_ptr<Base> are not covariant. So you must return the same type from all clone functions in that case.

0

精彩评论

暂无评论...
验证码 换一张
取 消