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

时间:2013-12-18 09:21:48

标签: c++ clone virtual member non-virtual-interface

我有一个抽象类说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;}

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


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

3 个答案:

答案 0 :(得分:1)

除非你为你的类声明一个复制构造函数图语言给你一个 au gratis ,它是公开的。你不想要这个免费的公共拷贝构造函数。它会导致切片。为类图保护你的复制构造函数。非抽象派生类的复制构造函数应调用此受保护的复制构造函数。有了这个,克隆成员函数就像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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

为图类添加受保护的访问者:

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

虽然您无法直接访问该成员,但您可以访问该乘数。