|
|||||||||||
|
Section 22:
|
[22.5] How do you define a copy constructor or assignment operator for a class that contains a pointer to a (abstract) base class?
If the class "owns" the object pointed to by the (abstract) base class pointer, use the Virtual Constructor Idiom in the (abstract) base class. As usual with this idiom, we declare a pure virtual clone() method in the base class:
class Shape {
public:
...
virtual Shape* clone() const = 0; // The Virtual (Copy) Constructor
...
};
Then we implement this clone() method in each derived class. Here is
the code for derived class Circle:
class Circle : public Shape {
public:
...
virtual Circle* clone() const;
...
};
Circle* Circle::clone() const
{
return new Circle(*this);
}
(Note: the return type in the derived class is
intentionally different from the one in the base
class.)
Here is the code for derived class Square:
class Square : public Shape {
public:
...
virtual Square* clone() const;
...
};
Square* Square::clone() const
{
return new Square(*this);
}
Now suppose that each Fred object "has-a" Shape object. Naturally the
Fred object doesn't know whether the Shape is Circle or a Square or ...
Fred's copy constructor and assignment operator will invoke Shape's
clone() method to copy the object:
class Fred {
public:
// p must be a pointer returned by new; it must not be NULL
Fred(Shape* p)
: p_(p) { assert(p != NULL); }
~Fred()
{ delete p_; }
Fred(Fred const& f)
: p_(f.p_->clone()) { }
Fred& operator= (Fred const& f)
{
if (this != &f) { // Check for self-assignment
Shape* p2 = f.p_->clone(); // Create the new one FIRST...
delete p_; // ...THEN delete the old one
p_ = p2;
}
return *this;
}
...
private:
Shape* p_;
};
|
||||||||||