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.
精彩评论