According to CppCoreGuideline, I should disable the copy constructor of a base class and propose a clone method: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rc-copy-virtual
For example:
class B {
public:
explicit B() = default;
B(B&&) = default; // Move constructor
B& operator=(B&&) = default; // Move assignment operator
B(const B&) = delete; // Copy constructor
B& operator=(const B&) = delete; // Copy assignment
virtual ~B() = default;
virtual unique_ptr<B> clone()
{
return unique_ptr<B>{new B{*this}}; // how do this without copy constructor ?
}
private:
int c;
int d;
};
class D : public B {
public:
explicit D() = default;
D(D&&) = default; // Move constructor
D& operator=(D&&) = default; // Move assignment operator
D(const B&) = delete; // Copy constructor
D& operator=(const D&) = delete; // Copy assignment
virtual ~D() = default;
virtual unique_ptr<B> clone() override
{
// how can I copy all private data member of base class ???
}
};
but how can I copy all private data member in clone method? Obviously I'll use the CRTP pattern : C++: Deep copying a Base class pointer
We can also use the clone() method to get a copy of an object from an existing object of the class. But the Copy constructor is better to use than the clone() method because of the following reasons: 1. It is easier to implement and use a copy constructor than the clone() method.
You can simply use copy = Object. create(originalObj); but you may want to use copy = JSON. parse(JSON. stringify(originalObj)); to avoid any reference in sub objects (Deep Copy).
To clone an object, use the Object class's clone() method. It is the quickest way to duplicate an array. The class whose object clone we wish to generate must implement the Cloneable interface. If the Cloneable interface is not implemented, the clone() function throws a CloneNotSupportedException .
Map clonedObject = JSON. decode(JSON. encode(object)); If you're using a custom class as a value in the object to clone, the class either needs to implement a toJson() method or you have to provide a toEncodable function for the JSON.
I think the simplest way is to actually make the special members protected
instead of deleted
. This still prevents slicing, but makes it easier to implement clone()
. Note that both the copy and move members need to be treated this way.
class B {
public:
// if this is truly intended to be a polymorphic base class, it probably
// doesn't make sense for the base to be able to clone itself.
virtual unique_ptr<B> clone() = 0;
protected:
B(B const& ) = default;
B& operator=(B const& ) = default;
private:
int c;
int d;
};
Which also allows the derived classes to do this easily:
class D : public B {
public:
D(D const& ) = default; // this is safe now
D& operator=(D const& ) = default;
unique_ptr<B> clone() override {
return unique_ptr<D>(new D(*this));
}
// ...
};
Rather than disabling the copy constructor, consider marking it protected. That way, clients of the class can't accidentally create a copy, but instances of the class can invoke the copy constructor as needed to implement the clone
function. You can use the defaulted version of the copy constructor assuming you aren't doing any explicit resource management. Then, to implement clone
, you can do something like this:
virtual unique_ptr<B> clone() override
{
return make_unique<D>(*this);
}
This invokes the object's own (protected) copy constructor, which in turn will invoke the base's (protected) copy constructor, etc.
As a note, there's no need to use CRTP here. Using good old fashioned copy constructors should be all you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With