调用基类克隆实现

时间:2018-05-15 13:27:14

标签: c++ c++11 polymorphism clone

尝试实现克隆模式,但坚持使用函数调用顺序:

我有一个带有多态类(Script)矢量的 Base 类。

基础类实现了一个克隆函数,它实质上是自己的所有成员(mScripts vector)的副本。

派生类还实现了自己的克隆功能版本,并负责其成员克隆。这个时刻只是一个整数。

问题:我应该如何调用基础类'克隆功能,在派生类'克隆函数,所以每个类都负责克隆自己的成员?

作为一个丑陋的解决方法,现在,我所有的衍生课程'克隆函数手动执行mScripts向量克隆,基本上重复相同的代码。

class Base
{
public:

    virtual std::unqique_ptr<Base> clone()
    {
        std::unique_ptr<Base> clonedInstance = std::make_unique<Base>();

        //clone the underlying vector
        for(int i = 0; i < mScripts.size(); ++i)
        {
            clonedInstance->mScripts.push_back(std::move(mScripts[i]->clone()));
        }

        return std::move(clonedInstance);
    }

    std::vector<std::unique_ptr<ScriptBase>>    mScripts;   //polymorphic array
};



class Derived : public Base
{
public:

    Derived(const int x) : Base(), mX(x)
    {
    }

    std::unqique_ptr<Base> clone()
    {
        //calling base::clone() here?

        return std::unique_ptr<Base> clonedInstance = std::make_unique<Derived>(mX);
    }

private:

    int mX;

};

2 个答案:

答案 0 :(得分:2)

正确实现复制构造函数,然后每个克隆函数只是return std::make_unique<Derived>(*this);

class Base
{
public:
    Base() = default;
    Base(const Base& rhs) // default is not fine here
    {
        for (const auto& script : rhs.mScripts)
        {
            mScripts.push_back(script->clone());
        }
    }
    virtual ~Base() = default;

    virtual std::unique_ptr<Base> clone() const
    {
        return std::make_unique<Base>(*this);
    }

    std::vector<std::unique_ptr<ScriptBase>> mScripts;   //polymorphic array
};

class Derived : public Base
{
public:
    Derived(int x) : Base(), mX(x) {}
    Derived(const Derived&) = default; // Default is fine here

    std::unique_ptr<Base> clone() const override
    {
        return std::make_unique<Derived>(*this);
    }

private:
    int mX;
};

答案 1 :(得分:1)

例如,定义一个接受Base作为参数的附加构造函数。如果您不想公开它,请将其设为private

struct Base {
     Base(Base &&) = default;
};

class Derived: public Base {
    Derived(Base &&b, int x): Base(std::move(b)), mX(x) {}
public:
    std::unique_ptr<Base> clone() const {
        auto retBase{Base::clone()};
        return std::make_unique<Derived>(std::move(*retBase), mX);
    }
};

(无论如何,您的Base并非易于复制。)

另一种方法是添加模板化克隆,当所有Base克隆在类似CRTP的模板化函数内完成时,可能会对返回值进行进一步调整:

class Base {
protected:
    template<typename Concrete> std::unique_ptr<Base> recreate() const {
         std::unique_ptr<Base> retVal{std::make_unique<Concrete>()};
         // ???????
         return retVal;
    };
public:
    virtual std::unique_ptr<Base> clone() const { return recreate<Base>(); }
};

struct Derived: public Base {
    std::unique_ptr<Base> clone() const {
        auto retVal{recreate<Derived>()};
        retVal->mX = mX;
        return retVal;
    }
};