C++ elegantly clone derived class by calling base class

不想你离开。 提交于 2019-12-02 04:30:31

问题


I have a need to clone a derived class given only a reference or pointer to the base class. The following code does the job, but doesn't seem elegant, because I'm putting boilerplate code into many derived classes C, D, E that are siblings of B (not shown) that just calls the default copy constructor of each. Isn't that what the default copy constructor is for, if only it could be virtual?

Is there a better way?

Making a virtual assignment operator would be wrong, as I don't want C to assign to B, B to D, etc, just clone B, C, D or E.

#include <iostream>
using namespace std;

class A {
public:
    virtual ~A() {}
    virtual A* clone()=0;
};

class B : public A {
    int i;
    public:
    virtual A* clone() { 
        cout << "cloned B" << endl;
        return new B(*this);
    }
    virtual ~B() { cout << "destroyed b" << endl; }
};

int main() { 
    A* a = new B(); 
    A* aa = a->clone();
    delete a; 
    delete aa; 
    return 0;
}

回答1:


You could always stick all the cloning logic into its own class in the middle of the hierarchy:

template <class Derived, class Base>
class CloneCRTP : public Base {
public:
    Derived* clone() const override {
        return new Derived(static_cast<Derived const&>(*this));
    }
};

And then:

class B : public CloneCRTP<B, A>
{
    int i;
public:
    virtual ~B() { cout << "destroyed b" << endl; }        
};

No more boilerplate.




回答2:


You can rely on the CRTP idiom.
It follows a minimal, working example:

struct B {
    ~virtual ~B() { }
    virtual B* clone() = 0;
};

template<class C>
struct D: public B {
    B* clone() {
        return new C{*static_cast<C*>(this)};
    }
};

struct S: public D<S> { };

int main() {
    B *b1 = new S;
    B *b2 = b1->clone();
    delete b1;
    delete b2;
}


来源:https://stackoverflow.com/questions/36189838/c-elegantly-clone-derived-class-by-calling-base-class

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!