【问题标题】:Clone method with a non virtual interface and some private variables具有非虚拟接口和一些私有变量的克隆方法
【发布时间】:2013-12-18 09:21:48
【问题描述】:

我有一个抽象类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 类中分配乘数,而不需要让每个图形知道它的乘数。

【问题讨论】:

  • multiplier 是私有的,所以你要么需要一个受保护的 setter,要么需要一个将 multiplier 作为参数的构造函数。子类构造函数然后可以将乘数值传递给父构造函数。
  • @Thrustmaster 我希望能够避免编辑所有现有的派生图形,并为我仍然需要编写的那些保留轻型构造函数。确实没有其他理由让数字看到其乘数。

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


【解决方案1】:

除非您为自己的类 Figure 声明一个复制构造函数,否则该语言会为您提供一个au gratis,并且它是公开的。你不想要这个免费的公共复制构造函数。它会导致切片。使您的类 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

【讨论】:

  • 1) 谢谢,我的不精确! 2)是的,它必须使用克隆方法。 3)当然!
【解决方案2】:

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

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

【讨论】:

  • 在 Derivated 类中,clone 方法返回 Derivated * 只是一个错字吗?我对默认复制 ctors 不是很熟悉,Derivated(Derivated const&)=default; 是否也在调用 Base(Base const&)
【解决方案3】:

为图形类添加一个受保护的访问器:

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

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

【讨论】:

  • 我不清楚我应该如何通过这样做来解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-04
  • 2015-03-24
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多