【问题标题】:C++: Duplicating a tree of derived elementsC ++:复制派生元素树
【发布时间】:2015-10-28 16:50:11
【问题描述】:

我有一个基类和几个派生类。基类如下所示:

class Base
{
    int type; //the derived type the object belongs to
    int nOfChildren;
    Base** children; //each child can be any of the derived types
    ...
}

现在我需要复制Base 的一个实例。由于递归,需要一个虚方法Base::duplicate()。里面应该写什么似乎也很清楚:

Base temp = new Base();
temp->type = temp;
temp->nOfChildren = nOfChildren;
temp->children = new Base*[nOfChildren];

除此之外,还不是很清楚。

我是将每个temp->children[i] 分配为Base 对象还是派生对象?我是否需要一个 case 语句来满足所有可能的派生类型?我是否需要为每个派生类型实现duplicate() 方法,即使是那些不包含除基类之外的其他信息的类型? (如果派生类包含更多信息,那么很明显我需要一个单独的机制。有几个派生类不包含比基类更多的数据,尽管它们包含未显示的handler() 方法的不同实现。)

【问题讨论】:

    标签: c++ inheritance recursion deep-copy


    【解决方案1】:

    你是对的,克隆多态对象需要一个虚方法。 OTOH,您可以利用 C++ 功能来简化编写过程:

    class Child : public ICloneable {
    public:
        // stuff...
        Child *clone() const { return new Child(*this); }
    }
    

    另外,不要将对象集合放入数组中!请改用std::vector

    class Base
    {
        // stuff...
        std::vector<Base*> children;
    }
    

    更好的是,使用智能指针将克隆操作包装成对象std::vector就能透明管理。

    template<typename T>
    struct clone_ptr {
        T *object;
    
        clone_ptr() : object(new T()) {}
        clone_ptr(T *object_) : object(object_) {}
        clone_ptr(clone_ptr<T> const &other) : object(other.object->clone()) {}
        clone_ptr<T> &operator=(clone_ptr<T> other) {
            std::swap(object, other.object);
            return *this;
        }
    
        ~clone_ptr() { delete object; }
    };
    

    这样你就可以在你的 Base 中使用 std::vectorclone_ptrs

    class Base
    {
        // stuff...
        std::vector<clone_ptr<Base>> children;
    }
    

    只要您在每个类中实现 clone(),每个对象都会自动复制到相同多态类型的对象中。向量将以与其他数据成员相同的方式被 C++ 编译器自动克隆。

    【讨论】:

    • 需要检查您的clone_ptr::operator= 中的自我分配,否则为可靠答案。
    • @Mr.kbok。 “另外,不要将对象集合放入数组中!改用std::vector。”我需要多次遍历这些树,并且性能是一个问题。除了少数例外,我提前知道每种节点的子节点数量。在这些情况下,<:vector> 是否与数组竞争?
    • @user3697176 是的,使用 std::vector 预先分配所需的缓冲区大小并避免复制。使用 emplace_back 将对象直接构造到向量中,使用 operator[] 绕过边界检查
    • 启用优化后,以这种方式使用的 std::vector 具有与数组相同的性能,并增加了安全性和便利性。
    • @Barry: 是的,我写那门课有点快 :) 我在投掷克隆体时增加了安全性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多