34

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.

svick
  • 236,525
  • 50
  • 385
  • 514
eold
  • 5,972
  • 11
  • 56
  • 75
  • 1
    This seems like an exact duplicate of this question: http://stackoverflow.com/questions/5148706/copying-a-polymorphic-object-in-c. See the accepted answer by Michael Anderson there. – AVH Apr 20 '11 at 13:44
  • 1
    @Darhuuk: I'm not quite sure what the SO policy on duplicates is, but this question is a little different. The OP here asked about the way to solve this problem, whereas the OP of that question asked whether cloning is a good C++ approach. It's obviously related, just not sure if it's an "exact duplicate". – ltjax Apr 20 '11 at 14:02
  • @Itjax Fair enough, it's just that the answer given there is more or less exactly what the OP is looking for. Although I guess your answer below is even more convenient :). – AVH Apr 20 '11 at 14:20

2 Answers2

48

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> { ... };
ltjax
  • 15,837
  • 3
  • 39
  • 62
2

An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.

sharptooth
  • 167,383
  • 100
  • 513
  • 979