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