How to deep cloning in inherited relationships? [duplicate] - c++

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:
class Base {}
Then a long line of derived classes:
class Derived_1:: public Base {}
class Derived_2:: public Derived_1{}
...
...
class Derived_n:: public Derived_M{}
And then I have another class:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy & dc) {}
}
Assuming the Base class and Derived_x class copy constructors are properly coded, what is the best way to write the copy constructor for DeepCopy. How can we know about the class that is in the basePtr of the object we are going to copy?
Only way I can think of is using RTTI, but using a long list of dynamic_casts seems not right. Besides it requires DeepCopy to know about the inheritance hierarchy of Base class.
The other method I saw is here. But it requires Base and Derived classes implement a clone method.
So is there a much easier, standard way of doing this?

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() )
{}
};

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())
{}
};

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++.

Related

C++ how to copy Polymorphic array of objects [duplicate]

I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.

Derived curiously recurring templates and covariance

Suppose I have a base class which cloning of derived classes:
class Base
{
public:
virtual Base * clone()
{
return new Base();
}
// ...
};
I have a set of derived classes which are implemented using a curiously recurring template pattern:
template <class T>
class CRTP : public Base
{
public:
virtual T * clone()
{
return new T();
}
// ...
};
And I attempt to derive from that further like this:
class Derived : public CRTP<Derived>
{
public:
// ...
};
I get compilation errors to the effect of:
error C2555: 'CRTP<T>::clone': overriding virtual function return type differs and is not covariant from 'Base::clone'
I realize this is probably a result of the compiler not fully knowing the inheritance tree for Derived when instantiating CRTP. Furthermore, replacing the return type (T*) with (Base*) also compiles. However, I would like to know if there is a work around which retains the above semantics.
A not-so-pretty workaround.
class Base
{
protected:
virtual Base * clone_p()
{
return new Base();
}
};
template <class T>
class CRTP : public Base
{
protected:
virtual CRTP* clone_p()
{
return new T;
}
public:
T* clone()
{
CRTP* res = clone_p();
return static_cast<T*>(res);
}
};
class Derived : public CRTP<Derived>
{
public:
};
Use dynamic_cast<> instead of static if you feel it's safer.
If you can live with having to use a different syntax for specifying complete types, you might do the following (warning: untested code):
Let's first start with the machinery:
// this gives the complete type which needs to be used to create objects
// and provides the implementation of clone()
template<typename T> class Cloneable:
public T
{
public:
template<typename... U> Cloneable(U&&... u): T(std::forward<U>(u) ...) {}
T* clone() { return new Cloneable(*this); }
private:
// this makes the class complete
// Note: T:: to make it type dependent, so it can be found despite not yet defined
typename T::CloneableBase::CloneableKey unlock() {}
};
// this provides the clone function prototype and also makes sure that only
// Cloneable<T> can be instantiated
class CloneableBase
{
template<typename T> friend class Cloneable;
// this type is only accessible to Clonerable instances
struct CloneableKey {};
// this has to be implemented to complete the class; only Cloneable instances can do that
virtual CloneableKey unlock() = 0;
public:
virtual CloneableBase* clone() = 0;
virtual ~CloneableBase() {}
};
OK, now the actual class hierarchy. That one is pretty standard; no CRTP intermediates or other complications. However no class implements the clone function, but all inherit the declaration (directly or indirectly) from CloneableBase.
// Base inherits clone() from CloneableBase
class Base:
public CloneableBase
{
// ...
};
// Derived can inherit normally from Base, nothing special here
class Derived:
public Base
{
// ...
};
Here's how you then create objects:
// However, to create new instances, we actually need to use Cloneable<Derived>
Cloneable<Derived> someObject;
Derived* ptr = new Cloneable<Derived>(whatever);
// Now we clone the objects
Derived* clone1 = someObject.clone();
Derived* clone2 = ptr->clone();
// we can get rid og the objects the usual way:
delete ptr;
delete clone1;
delete clone2;
Note that a Cloneable<Derived> is-a Derived (it is a subclass), therefore you need to use Cloneable only for construction, and can otherwise pretend to work with Derived objects (well, tyepinfo will also identify it as Cloneable<Derived>).

C++: Deep copying a Base class pointer

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:
class Base {}
Then a long line of derived classes:
class Derived_1:: public Base {}
class Derived_2:: public Derived_1{}
...
...
class Derived_n:: public Derived_M{}
And then I have another class:
class DeepCopy
{
Base * basePtr;
public:
DeepCopy(DeepCopy & dc) {}
}
Assuming the Base class and Derived_x class copy constructors are properly coded, what is the best way to write the copy constructor for DeepCopy. How can we know about the class that is in the basePtr of the object we are going to copy?
Only way I can think of is using RTTI, but using a long list of dynamic_casts seems not right. Besides it requires DeepCopy to know about the inheritance hierarchy of Base class.
The other method I saw is here. But it requires Base and Derived classes implement a clone method.
So is there a much easier, standard way of doing this?
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() )
{}
};
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())
{}
};
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++.

Performing a deep copy on derived classes

This has been bugging me lately. Say I have a base class Base. If I have multiple derived classes on top of Base, such as DerivedA and DerivedB, a deep copy gets to be a pain.
OtherClass(const OtherClass & _rhs)
{
//I have a list of Base *, now I must assign a class id to each derived class to properly create a new one.
//...
}
Is there any way to get around this?
You should define a clone method in your Base class:
virtual Base * clone() const = 0;
Each derived class implement that clone method:
virtual DerivedA * clone() const {
return new DerivedA(*this);
}
Then your OtherClass just has to iterate and call clone method over each instance of Base* in your list.

How to copy/create derived class instance from a pointer to a polymorphic base class?

I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.