独立构造或克隆物体

时间:2014-07-30 15:51:22

标签: c++ design-patterns clone copy-constructor

我有一个非常复杂的课程。它在大型数组中有许多不同级别的数据。我在许多不同的环境中使用这个对象。

问题:我们会在传递此对象时制作此对象的副本,但每个地点对需要复制的内容以及需要忽略的内容有不同的要求。结果,代码变得越来越难看,有5-6种不同的方式,人们从复制构造函数到克隆函数将所有东西复制到一起。它变得丑陋。

我想做什么:我希望以外部可扩展的方式解耦对象的构造。如果某人有一次性特殊复制情况,我希望他们能够在相关文件中创建一个函数或类,然后将其传递给克隆函数。

我已经考虑了一段时间,但是想不出有任何方法让外部函数/对象访问私有成员(没有强制它。)这是我认为可以工作的一个例子:

class Dolly
{
public:
    Dolly (int c = 0) : c(c) {}

    struct Cloner
    {
        virtual Dolly* operator()(Dolly const& p) const
            { return new Dolly(p.c + 1); }
    } cloneDeep;

    Dolly* clone();
    Dolly* clone(Cloner const& cloner)
        { return cloner(*this); }

protected:
    int c;
};

class ShallowCloner : public Dolly::Cloner
{
    Dolly* operator()(Dolly const& p) const
        { return new Dolly(p.c + 2); } // Error: cannot access c because its protected
} cloneShallow;

但派生的ShallowCloner无法访问其嵌套的基类'父母的受保护成员(哇,什么句子。)

如果您知道任何可能有用的解决方案或设计模式,请与我们联系。感谢

修改

经过一夜好眠,我决定使用标志来控制数据的复制。它与Mark B的答案没有什么不同,但由于旗帜的帮助,从长远来看,代码并不多。这是我正在考虑的当前框架(这是一个非常简化的例子):

class Dolly
{
public:
    enum CopyData {
        D1 = 0x01,
        D2 = 0x02,
        D3 = 0x04,
        D4 = 0x08,
        DEEP = D1 | D2 | D3 | D4
    };

    Dolly(int d1 = 0, int d2 = 0, int d3 = 0, int d4 = 0) : 
            d1(d1), d2(d2), d3(d3), d4(d4) {}

    Dolly(Dolly const& cpy, int copyFlags = DEEP) {
        copyDataFrom(cpy, copyFlags);
    }

    Dolly* clone(int copyFlags) {
        return new Dolly(*this, copyFlags);
    }

    void copyDataFrom(Dolly const& cpy, int copyFlags) {
        if (copyFlags & D1) {
            copyD1From(cpy);
        }
        if (copyFlags & D2) {
            copyD2From(cpy);
        }
        if (copyFlags & D3) {
            copyD3From(cpy);
        }
        if (copyFlags & D4) {
            copyD4From(cpy);
        }
    }

    // Note that the real copies are more complex than this
    inline void copyD1From(Dolly const& cpy) { d1 = cpy.d1; }
    inline void copyD2From(Dolly const& cpy) { d2 = cpy.d2; }
    inline void copyD3From(Dolly const& cpy) { d3 = cpy.d3; }
    inline void copyD4From(Dolly const& cpy) { d4 = cpy.d4; }

protected:

    int d1;
    int d2;
    int d3;
    int d4;
};

int main()
{
    Dolly dolly(1,2,3,4);
    //Copy using constructor
    Dolly dolly2(dolly, Dolly::D1 | Dolly::D2);
    //Copy using clone
    Dolly* dolly3 = dolly.clone(Dolly::D3 | Dolly::D4);
    delete dolly3;
    //Copy using copyFrom
    Dolly dolly4;
        // Maybe do stuff here...
    dolly4.copyDataFrom(dolly, Dolly::D1 | Dolly::D3);
   return 0;
}

这为类增加了很多代码,但它确实保持干净并且安全。所有复制都保存在一个地方。受保护的和私有的变量保持私密。并且API保持相当简单(< ---非常重要!)用户仍然可以使用标志创建自定义副本定义。也许我甚至可以使用一些助推变法魔法减少代码。无论如何,如果您有任何其他想法,我仍然愿意听取他们的意见。

1 个答案:

答案 0 :(得分:0)

使用嵌套类的方法与使用friend的方法大致相同,只是由于嵌套而隐式存在。如果您开始允许外部类或方法访问私有内部以进行此复制,则会鼓励错误使用此类访问并绕过公共接口。

相反,我要建议的是使用标记的构造函数在类中强制执行一致的复制机制:

struct DeepCopy {};
struct ShallowCopy {};
struct MagicCopy {};

class BigThing
{
public:
    BigThing() {}

    BigThing(const BigThing& right);  // Don't implement.

    BigThing(const BigThing& right, DeepCopy);  // Do the deep copy.

    BigThing(const BigThing& right, ShallowCopy);  // Do the shallow copy.

    BigThing(const BigThing& right, MagicCopy);  // Do the magic copy.
};

int main()
{
    BigThing b1;
    BigThing b2(b1, DeepCopy());
    BigThing b3(b1, MagicCopy());
}