5

如果我有一个指向派生自抽象基类的对象的指针(因此我无法创建该类的新对象),并且我希望制作所述对象的深层副本,是否有比实现该对象更简洁的方法让抽象基类创建一个新的纯虚copy函数,每个继承类都必须实现?

4

3 回答 3

10

不,但该copy方法不一定是痛苦的:

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

(假设你已经有一个拷贝构造函数,如果你需要一个深拷贝,你就会有)。

于 2011-01-21T03:38:47.413 回答
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 的绝对事实足以说服大多数人采用正常方法。但是,阻止更改基类是有原因的,它可能很有用。

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

于 2011-01-21T03:39:53.027 回答
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

于 2011-01-21T04:28:20.850 回答