Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clone an object without copy constructor

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

like image 894
Joseph Garnier Avatar asked Oct 24 '17 19:10

Joseph Garnier


People also ask

What is the alternative for copy constructor in Java?

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.

How do you clone an object without references?

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

How do you clone an object?

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 .

How do you clone an object in DART?

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.


2 Answers

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));
    }
    // ...
};
like image 178
Barry Avatar answered Oct 11 '22 07:10

Barry


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.

like image 3
templatetypedef Avatar answered Oct 11 '22 08:10

templatetypedef