【问题标题】:Making a copy of an object of abstract base class复制抽象基类的对象
【发布时间】:2011-06-12 21:50:43
【问题描述】:

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

【问题讨论】:

  • 是什么让你觉得它效率低下?
  • @GMan “效率低下”,因为它需要程序员做大量工作,相比之下,一些漂亮的单行技巧或可以完成同样事情的东西(我有时会发现Stackoverflow 上的案例)
  • 那么你想要的词是“简洁”。您可能应该在问题中详细说明这一点。并明确表示您的意思是可维护性和清洁度,而不是性能。
  • @GMan 谢谢,我已经更正了这个问题!

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


【解决方案1】:

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

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

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

【讨论】:

  • 您需要在基类中将copy 方法设为纯虚拟,因此如果您忘记提供它,编译器会告诉您。
  • @Mark - 这只会提供一种虚假的安全感,因为任何孙辈也可能会忘记。
  • @Noah,太真实了。但这只是避免生孙的原因之一,我可以提供其他人。
【解决方案2】:

建议的“复制”,通常称为“克隆”是正常的方法。另一种方法是使用 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 的绝对事实足以说服大多数人采用正常方法。但是,阻止更改基类是有原因的,它可能很有用。

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

【讨论】:

    【解决方案3】:

    不久前,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

    【讨论】:

      猜你喜欢
      • 2018-07-11
      • 1970-01-01
      • 1970-01-01
      • 2012-07-04
      • 2011-09-06
      • 2020-04-12
      • 1970-01-01
      • 1970-01-01
      • 2020-03-12
      相关资源
      最近更新 更多