Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

The best way to implement cloneable c++ classes?

I have seen solutions (including in this site) to the problem of having to implement a clone method in a class, so it returns a heap-allocated clone of itself even if we only have the Baseclass.

The problem come up when you have to implement in a lot of classes the same method again and again, and I remember a way of doing this when you only have to inherit from a template class (name it Cloneable) so it implements it, but the way i’m trying to do it doesn’t work:

template<typename T, typename B> class Cloneable{
public:
    B* clone(){return new T(*this);}
};

class Bottom {
public:
    virtual void sayhi() = 0;
    virtual Bottom* clone() = 0;
};

class Middle: public Cloneable<Middle, Bottom>, public Bottom {
public:
    void sayhi() override {cout << "Hi from the Middle" << endl;}
};

//class Top: public Middle ...?

int main() {
    Bottom* b1 = new Middle();
    b1->sayhi();
    delete b1;
}

I remember that the person that showed this to me actually did it with just one argument in Cloneable, but anyways, i would thank any way that you can imagine of doing this.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You could use the Curious Recurring Template Pattern where a derived class actually derives from an instanciation of it base class depending on itself. Demo:

#include <iostream>

template<typename T>
class Clonable {
public:
    T* clone() {
        return new T { * static_cast<T *>(this)};
    }
};

template<class T>
class Base : public Clonable<T> {
public:
    int x = 2;

    virtual ~Base() {}
};

class Derived : public Base<Derived> {
public:
    int y = 3;
};

int main() {
    Derived d;

    d.y = 6;

    Derived *c = d.clone();
    std::cout << c->x << ' ' << c->y << '\n';
    delete c;
}

It compiles with no warning and correctly outputs 2 6, proving that no slicing occurred.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading