I searched around and seems in order to perform this I need to change my Base class and want to know if this is the best approach. For example, I have a Base class:
I think that templates are the best way to go in this situation:
template<typename Sub>
class DeepCopy
{
Base *base;
DeepCopy(Sub *sub)
{
base = new Sub(*sub); // use copy constructor
}
}
This does mean that DeepCopy
's are un-assignable to each other, but that's the price you pay with C++.
Using an approach that employs a clone()
function is a good solution. Note using the CRTP (the curiously recurring template pattern) can save you some of the work. The way you do it is by introducing an intermediate level (called BaseCRTP
below) which is a template and implements the clone()
function. When you derive your actual classes, use them as the template argument of the base they are derived from. They will get the clone()
function implemented for them automatically. Make sure the derived classes implement a copy constructor (or be sure the default is what you need).
/* Base class includes pure virtual clone function */
class Base {
public:
virtual ~Base() {}
virtual Base *clone() const = 0;
};
/* Intermediate class that implements CRTP. Use this
* as a base class for any derived class that you want
* to have a clone function.
*/
template <typename Derived>
class BaseCRTP : public Base {
public:
virtual Base *clone() const {
return new Derived(static_cast<Derived const&>(*this));
}
};
/* Derive further classes. Each of them must
* implement a correct copy constructor, because
* that is used by the clone() function automatically.
*/
class Derived1 : public BaseCRTP<Derived1> {
/*... should have an ordinary copy constructor... */
};
class Derived2 : public BaseCRTP<Derived2> {
/*... should have an ordinary copy constructor... */
};
You can then obviously implement the DeepCopy
class in the usual way:
class DeepCopy
{
Base *basePtr;
public:
DeepCopy(const DeepCopy &dc)
: basePtr(dc.basePtr->clone())
{}
};
You need to use the virtual copy pattern: provide a virtual function in the interface that does the copy and then implement it across the hierarchy:
struct base {
virtual ~base() {} // Remember to provide a virtual destructor
virtual base* clone() const = 0;
};
struct derived : base {
virtual derived* clone() const {
return new derived(*this);
}
};
Then the DeepCopy
object just needs to call that function:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy const & dc) // This should be `const`
: basePtr( dc.basePtr->clone() )
{}
};