Question

I have an abstract class say Figure and some derived classes: Circle, Square, ...

The class figure implements:

private:
  virtual double varea()=0;
  double multiplier;
public:
  virtual Figure * clone()=0;
  double area() { return varea()*multiplier; }

The figures, Square for instance, behave like this:

private:
  double L;
public:
  virtual Figure * clone() {return new Square(*this);}
  virtual double varea() {return L*L;}

I'm having difficulties to assign the variable multiplier when calling the method clone. What is the best way to achieve this? Of course this is just a stupid example with a number of workarounds, but in reality, with multiple levels of derivation, they are not so obvious, so please stick to this pattern.


Should I go for a virtual interface also for the method clone? In this way I can assign the multiplier directly in the Figure class without any need to let each figure know its multiplier.

Was it helpful?

Solution

Unless you declare a copy constructor for your class Figure the language gives you one au gratis, and it's public. You do not want this freebie public copy constructor. It will lead to slicing. Make your copy constructor for class Figure protected. Your copy constructor for the non-abstract derived classes should invoke this protected copy constructor. With this, the clone member function is as simple as new DerivedClass (*this):

class Figure {
private:
   virtual double varea()=0;
   double multiplier;
protected:
   Figure () : multiplier(1.0) {}
   Figure (const Figure& src) : multiplier(src.multiplier) {}
public:
   virtual Figure* clone()=0;
   double area() { return varea()*multiplier; }
};

class Square: public Figure {
private:
   virtual double varea() {return L*L;}
   double L;
public:
  Square(const Square & src) : Figure(src), L(src.L) {}
  virtual Figure* clone() {return new Square(*this);}
};

Note well:

  • I made Square::varea() private because that's how it's declared in class Figure. Exposing a parent class's private method as public in a derived class typically is a bit dubious.
  • There's an issue with the assignment operator. I'll leave this up to you.
  • You need some way to set the multiplier.

OTHER TIPS

Inheritance connect awkwardly with copy semantics. However, one solution could be let the copy constructor do the job :

struct Base
{
public:
    Base()=default;
    virtual ~Base()=default;

    virtual Base* clone()=0;

    Base& operator=(Base const &) = delete;
    Base(Base&&)=delete;
protected:
    Base(Base const&) = default;
};

struct Derivated : Base
{
public:
    Derivated()=default;

    virtual Derivated * clone()
    {
        return new Derivated (*this);
    }
protected:
    Derivated(Derivated const&) = default;
};

Add a protected accessors to the figure class:

protected:
  double getMultiplier() { return multiplier; }
  void setMultiplier(double newValue) { multiplier = newValue; }

than you'll have access to the multiplier although you'll not have direct acces to the member..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top