1
class Cloneable
{
 public:
   virtual Cloneable* clone() const = 0; //return copy of itself
   virtual ~Cloneable() {}
};

class A
{
 public:
   A(const A& a);    
   ~A();  

 private:
   Cloneable* b;
   Cloneable* c;
   std::string* s;     
};

A::~A()  
{
 delete b;
 delete c;
 delete s;
}

Please, help me to understand cloneable pattern. I don't understand how to implement constructor, copy constructor of class A and how can I use it?

  • 1
    I disagree with this being marked as too broad, or "a good answer would be too long". The question makes sense and user3684240 gives a good answer. – ROX Jul 07 '16 at 16:12

1 Answers1

3

You first of all need to distinguish between the copy constructor and the clone pattern.

A copy constructor is a constructor that creates a copy of a class.

MyClass a;
MyClass copy(a); // calls the copy constructor

You (usually) don't need to implement it yourself, the compiler will create a so-called implicit copy constructor for you. If you however need to implement (e.g. because you write a class that manages a resource), please consider the rule of five (Rule-of-Three becomes Rule-of-Five with C++11?).

A copy constructor is not virtual (in fact, constructors are never virtual).

A typical use case for the clone pattern is this:

#include <memory>
class MyAbstractClass {
  virtual void someFunction();
};
class MyHeir : public MyAbstractClass {
  virtual void someFunction() override { /* TODO */ }
};
class MyHeir2 : public MyAbstractClass {
  virtual void someFunction() override { /* TODO */ }
};
std::unique_ptr<MyAbstractClass> ptr1 = std::make_unique<MyHeir>();
std::unique_ptr<MyHeir> clone; // TODO: clone

There is no way for the compiler to know at compile time whether ptr1 contains an instance of MyHeir or of MyHeir2. That's why you need the clone pattern. You basically just implement a virtual function that copies the class (read: calls the copy constructor).

// in MyAbstractClass
virtual MyAbstractClass* clone() = 0;
// in MyHeir
virtual MyHeir * /* return type covariance */ clone() {
  return new MyHeir(*this); // call to the (implicit) copy constructor
}
// in MyHeir2
virtual MyHeir2 * /* return type covariance */ clone() {
  return new MyHeir2(*this);
}

Now you can do:

std::unique_ptr<MyHeir> clone = ptr1->clone();
user3684240
  • 1,420
  • 2
  • 12
  • 18