Cloning

We have seen the power of polymorphism through the use of base class pointers. Polymorphism is fundamental to object oriented design. This being the case, it is often the case that a class will contain a pointer to a base class. When this occurs, making copies of that class requires some care and the use of "cloning".

Let suppose Fred is a class that contains a pointer to a Shape (our abstract base class) and that Fred supports the usual operations -- constructor, destructor, copy constructor and assignment operator.

class Fred { public: Fred( ); ~Fred( ); Fred( const Fred& fred); Fred& operator= (const Fred& rhs); // other public methods private: Shape *m_pShape; // other private data members }; If Fred is the "owner" of the object pointed to (i.e. Fred is responsible for deleting the object), care must now be taken when writing the copy constructor and assignment operator. Why? Let's take a look. We know that we need to perform a deep copy so that we don't have two different Fred objects pointing to the same shape. We don't just want to copy m_pShape from rhs, but we want to allocate our own memory and copy the contents of *(rhs.m_pShape) into our newly allocated memory.

The problem is that we don't know if rhs.m_pShape is pointing to a Circle, a Triangle, a Rectangle or some other kind of Shape. Since that's the case, we don't know which derived class' copy constructor to use. The solution is to define a pure virtual Clone( ) method in the Shape class. This function is then called in the copy constructor or assignment operator and polymorphism is used to call Clone() for the appropriate derived class. Each derived class' Clone( ) returns a pointer to a new dynamically allocated copy of itself using its own copy constructor. In effect, Clone( ) is an indirect, polymorphic way to copy a derived class that's pointed to by a base class pointer. Here's some of the code.

// Fred's copy constructor Fred::Fred (const Fred& rhs) { m_pShape = rhs.m_pShape->Clone( ); // code to handle the other data members } // define Clone( ) as pure virtual in Shape class Shape { public: virtual void Draw ( ) const = 0; // pure virtual method virtual void Error ( ) const; // virtual method void ObjectID ( ) const; // non-virtual method // pure virtual Clone function virtual Shape* Clone( ) const = 0; }; // define Clone in Circle class Circle : public Shape { public: virtual void Draw( ) const; // method for drawing a circle virtual void Error ( ) const; // overriding Shape::Error( ) virtual Circle* Clone( ) const; }; // implement Clone in Circle // This one line of code calls Circle's // copy constructor Circle* Circle::Clone( ) const { return new Circle( *this ); } Implement Clone( ) in the same manner for all derived classes

Check out this webpage for more example code and further discussion of cloning.


Dennis Frey
Last modified: Tue Nov 16 09:00:19 EST 2004