As Scott Myers wrote, you can take advantage of a relaxation in C++'s type-system to declare clone() to return a pointer to the actual type being declared:
class Base
{
virtual Base* clone() const = 0;
};
class Derived : public Base
{
virtual Derived* clone() const
};
The compiler detects that clone() returns an pointer to the type of the object, and allows Derived to override it to return a pointer to derived.
It would desirable to have clone() return a smart pointer that implies transfer of ownership semantics, like the following:
class Base
{
virtual std::auto_ptr<Base> clone() const = 0;
};
class Derived : public Base
{
virtual std::auto_ptr<Derived> clone() const;
};
Unfortunately, the relaxation of the conventions does not apply to templated smart pointers, and the compiler will not allow the override.
So, it seems I am left with two options:
Is one of these approaches preferred? Or is there a way for me to eat my transfer of ownership semantics and have my strong type safety too?
Use the Public non-virtual / Private virtual pattern :
class Base {
public:
std::auto_ptr<Base> clone () { return doClone(); }
private:
virtual Base* doClone() { return new (*this); }
};
class Derived : public Base {
public:
std::auto_ptr<Derived> clone () { return doClone(); }
private:
virtual Derived* doClone() { return new (*this); }
};