制作抽象基类的对象的副本

时间:2011-01-21 03:29:32

标签: c++ inheritance pointers derived-class deep-copy

如果我有一个指向从抽象基类派生的对象的指针(因此我无法创建该类的新对象),并且我希望对所述对象进行深度复制,是否有更简洁的方法实现这一点,而不是让抽象基类创建一个新的纯虚拟copy函数,每个继承类必须实现它?

3 个答案:

答案 0 :(得分:9)

不,但copy方法不一定很痛苦:

class Derived : public Base
{
  public:
    Base *copy() const
    {
        return new Derived(*this);
    }
};

(假设您已经有一个复制构造函数,如果您需要深层复制,那么您将拥有它。)

答案 1 :(得分:1)

建议的'副本',通常称为'克隆'是正常方法。另一种方法是使用rtti查找正确的处理程序然后在派生类型上调用复制构造函数的工厂和调度。

struct Abc
{
    virtual void who() const = 0;
};

struct A : Abc
{
    virtual void who() const { std::cout << "A" << std::endl;}
};

template<class T>
Abc* clone(Abc* abc)
{
    T* t = dynamic_cast<T*>(abc);
    if (t == 0)
        return 0;
    return new T(*t);
}

struct B : Abc
{
    virtual void who() const { std::cout << "B" << std::endl;}
};

typedef Abc* (*Cloner)(Abc*);

std::map<std::string, Cloner> clones;

void defineClones()
{
    clones[ typeid (A).name() ] = &clone<A>;
    clones[ typeid (B).name() ] = &clone<B>;
}


Abc* clone(Abc* abc)
{
    Abc* ret = 0;
    const char* typeName  = typeid(*abc).name();
    if (clones.find(typeName) != clones.end())
    {
        Cloner cloner = clones[typeName];
        ret = (*cloner)(abc);
    }
    return ret;
}
void test ()
{
    defineClones();
    Abc* a = new A;
    Abc* anotherA = clone(a);
    anotherA->who();

    Abc* b = new B;
    Abc* anotherB = clone(b);
    anotherB->who();
}

虽然上述工作,但它使用rtti的纯粹事实足以说服大多数人采取正常方法。但是,它有一个阻止更改基类的原因,它可能很有用。

这有效吗?添加新类型的边际成本确实是一个单线程。问题是,很容易忘记在每个新类中添加该行。或者你可以看到它是一个好处,所有克隆代码都存在于一个文件中,我们不必更改支持的层次结构来处理它。

答案 2 :(得分:1)

前来有人在comp.lang.c ++中询问如何自动创建clone()函数。其他人提出了我扩展的想法。这些都不是经过测试的代码,我从未真正尝试过......但我认为它有效:http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c01181365d327b2f/9c99f46a8a64242e?hl=en&ie=UTF-8&oe=utf-8&q=comp.lang.c%2B%2B+noah+roberts+clone&pli=1