2

我有一个抽象类Figure和一些派生类:Circle, Square, ...

类图实现:

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 类中分配乘数,而无需让每个图形知道其乘数。

4

3 回答 3

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()私有是因为它是在 class 中声明的Figure。在派生类中公开父类的私有方法通常有点可疑。
  • 赋值运算符有问题。我会把这个留给你。
  • 你需要一些方法来设置multiplier.
于 2013-12-18T10:16:51.333 回答
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;
};
于 2013-12-18T10:18:12.653 回答
0

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

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

尽管您无法直接访问该成员,但您将可以访问乘数。

于 2013-12-18T09:29:10.883 回答