具有非虚拟接口和一些私有变量的克隆方法

Clone method with a non virtual interface and some private variables

本文关键字:变量 方法 虚拟 接口      更新时间:2023-10-16

我有一个抽象类说Figure和一些派生类:CircleSquare,...

类图实现:

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

这些数字,例如Square,表现如下:

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

调用方法克隆时,我很难分配变量乘数。实现这一目标的最佳方法是什么?当然,这只是一个愚蠢的例子,有许多解决方法,但实际上,通过多个级别的派生,它们并不那么明显,所以请坚持这种模式。


我是否也应该为方法克隆使用虚拟接口?通过这种方式,我可以直接在 Figure 类中分配乘数,而无需让每个数字知道其乘数。

除非你为你的类声明了一个复制构造函数,否则语言给你一个免费的,它是公开的。您不想要这个免费赠品公共复制构造函数。这将导致切片。使类的复制构造函数受图保护。非抽象派生类的复制构造函数应调用此受保护的复制构造函数。有了这个,克隆成员功能就像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);}
};

请注意:

  • 我把Square::varea()设为私有,因为这就是它在类Figure中声明的方式。在派生类中将父类的私有方法公开为公共方法通常有点可疑。
  • 分配运算符存在问题。我就交给你了。
  • 您需要某种方法来设置multiplier

继承与复制语义的笨拙连接。但是,一种解决方案可以让复制构造函数完成这项工作:

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;
};

将受保护的访问器添加到图形类:

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

比你可以访问乘数,尽管你不会直接访问会员。