如何克隆子类而不重复代码?

时间:2013-11-06 21:55:51

标签: c++ exception exception-handling clone

Class Plus继承自Expression类。

class Expression
{
 public:
  virtual Expression* clone() const = 0;
};
class Plus : public Expression
{
 public:
 Plus( Expression* lhs, Expression* rhs ) :Expression( lhs, rhs) {};
 Plus* clone() const;
};

我正在实施copy功能。如果其中一个clonePlus失败,则当前实现将泄漏内存。

Plus* Plus::clone() const  {
        return new Plus(tree_left->clone(), tree_right->clone());
}

我认为这样的事情可以解决问题:

Plus* Plus::clone() const  {
        Expression *tree_left_clone = nullptr;
        Expression *tree_right_clone = nullptr;
        Expression *plus_clone = nullptr;
        try {
             tree_left_clone = tree_left->clone();
             tree_right_clone = tree_right->clone()
             plus_clone = new Plus( tree_left_clone, tree_right_clone );
        } catch (const bad_alloc& e ) {
             delete tree_left_clone;
             delete tree_right_clone;
             delete plus_clone;
        }
        return plus_clone;
}

但是有许多类似的运营商,包括Minus,Times,Divided,Power等。我必须为所有这些运营商复制clone。有没有办法将此代码放入Expression? 我遇到的问题是clone中包含new Plus的行。

3 个答案:

答案 0 :(得分:1)

尝试类似的东西:

    Plus* Plus::clone() const  {
         auto_ptr<Expression> tree_left_clone(tree_left->clone());
         auto_ptr<Expression> tree_right_clone(tree_right->clone());
         return new Plus(tree_left_clone.release(), tree_right_clone.release());
    }

答案 1 :(得分:1)

使用智能指针而不是原始指针,您的代码不会泄漏:

class Expression;
typedef std::shared_ptr<Expression> ExpressionPtr;
class Expression
{
 public:
  virtual ExpressionPtr clone() const = 0;
};
class Plus : public Expression
{
 public:
 Plus( ExpressionPtr lhs, ExpressionPtr rhs ) :Expression( lhs, rhs) {};
 ExpressionPtr clone() const;
};

ExpressionPtr Plus::clone() const  {
    return std::make_shared<Plus>( tree_left->clone(), tree_right->clone() );
}

如果c ++ 11不可用,你可以使用boost :: shared_ptr。

答案 2 :(得分:1)

这就是智能指针的用途。您可以更改构造函数以接收std::unique_ptr

Plus( std::unique_ptr<Expression> lhs, std::unique_ptr<Expression> rhs )
  : Expression( lhs.release(), rhs.release() ) {}

并将其称为:

Plus* Plus::clone() const {
    std::unique_ptr<Expression> lhs( tree_left->clone() );
    std::unique_ptr<Expression> rhs( tree_right->clone() );
    return new Plus( std::move(lhs), std::move(rhs) );
}

但这应该只是开始。您还应该将存储指针视为std::unique_ptr,并尽可能避免使用普通指针。

相关问题