2016-03-23 14 views
2

Ich muss eine abgeleitete Klasse klonen, wenn nur eine Referenz oder ein Zeiger auf die Basisklasse angegeben wird. Der folgende Code macht den Job, scheint aber nicht elegant zu sein, weil ich den Code in viele abgeleitete Klassen C, D, E einfüge, die Geschwister von B sind (nicht gezeigt), die einfach den Standard-Kopierkonstruktor von jedem aufrufen. Ist das nicht der Standard-Kopierkonstruktor, wenn er nur virtuell sein könnte?C++ elegant abgeleitete Klasse durch Aufruf der Basisklasse

Gibt es einen besseren Weg?

ein virtueller Zuweisungsoperator zu machen wäre falsch, wie ich C zu B, B bis D, etc., nur Klon B, C, D oder E zuzuordnen nicht will

#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; 
} 

Antwort

4

Sie könnten immer halten alle das Klonen Logik in seine eigene Klasse in der Mitte der Hierarchie:

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

Und dann:

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

mo wieder basteln.

+2

keine vorformulierten, aber rekursive Vorlagen mit einziehe ... sollte ich vorsichtig sein, was ich wünsche! –

2

Sie können sich auf das CRTP-Idiom verlassen.
Es folgt eine minimale, Arbeitsbeispiel:

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; 
} 
Verwandte Themen