如何避免c ++中多态对象的clone()样板代码

时间:2011-06-08 18:11:50

标签: c++ polymorphism virtual

如果我想在C ++中克隆多态对象(即从其他B类派生的A类实例),最简单的方法似乎是给B一个虚拟克隆成员函数,必须由A看起来像这样

A* clone(){
    return new A(*this);
}

我的问题是,我发现这个不必要的样板代码,因为如果想要使用C ++的运行时多态特性,几乎总是需要它。如何规避?

由于

为什么我需要这个:

我的用例可以抽象为以下示例: 我有一个class Integral,它评估某个函数的积分。这样做,他们有一个指向class MathFunction的成员。此抽象类包含一个纯虚函数evaluate,它接受​​一个参数。我想实现我将创建class PowFunction : class MathFunction的幂函数。这个类有一个成员exponent,函数evaluate看起来像这样:

double evaluate(x){
    return pow(x,exponent);
}

如上所述,MathFunction的成员class Integral必须是多态的,这要求它是一个指针。用另一个问题回答评论者的问题。为什么我不想复制MathFunction对象?

我真的希望Integral“拥有”它的MathFunction,这意味着它可以改变参数(如exponent),而无需更改任何其他Integral对象的MathFunction。这意味着每个Integral都需要拥有自己的副本。这需要MathFunctions的clone()函数,不是吗?

我想到的另一个选择:如果几个Integral对象可以通过指向同一地址的指针共享相同的MathFunction,我可以创建Integral对象的副本而无需复制MathFunction。但在这种情况下,我将不得不使所有的属性const或某种方式readonly,这也不是很优雅。另外,哪个Integral对象应该处理删除MathFunction对象?

为什么需要这个:

您是否认真地说,只要您处理多态对象,就不需要复制操作?是什么让多态对象在这方面与其他对象不同?

使用这个论证,您也可以将复制构造函数和复制赋值运算符抛出C ++标准!

2 个答案:

答案 0 :(得分:9)

减少克隆多态对象的需要。真的,我很少在我自己的代码中找到这个需求,并且对这个问题的评论表明我并不孤单,如果你发现自己克隆了所有内容,那么你可能设计错了。

当然,永远不要无益,你确实可以使用奇怪的重复模板模式。

template<typename T> struct Clone {
    virtual T* clone() { return new T(static_cast<const T&>(*this)); }
};

答案 1 :(得分:3)

我用宏来处理这个问题...它很难看,但它可以避免不一致。

/** An interface that can be inherited by any class that wants to provide a Clone()
  * method that will return a copy of itself.
  */
class ICloneable
{
public:
   ICloneable() {}
   virtual ~ICloneable() {}

   virtual ICloneable * Clone() const = 0;
};
#define DECLARE_STANDARD_CLONE_METHOD(class_name) virtual ICloneable * Clone() const {new class_name(*this);}

[...]
public MyCloneableClass : public ICloneable
{
public:
   MyCloneableClass() {}

   DECLARE_STANDARD_CLONE_METHOD(MyCloneableClass);
};