Magix
Magix

Reputation: 5339

Copy an object derived from an abstract class

I have an abstract base class named component. It has derived non-abstract classes like resistor, generator etc...

In my circuit class, I have an heterogenous std::vector<sim::component*> named component_list, which I use to handle all the components inserted in the circuit.

Then I have the following function :

void circuit::insert(sim::component& comp, std::vector<sim::node*> nodes)

In the function definition, I want to copy the component named comp in order to insert a pointer to it in my component_list (so that I can manage its lifetime)

I tried something along those lines :

sim::component *copy = new sim::component(comp)

but of course, sim::component is abstract and I can't instanciate it

How can I make a copy of the object, which real class is unknown at compile-time ?

Upvotes: 1

Views: 136

Answers (1)

bipll
bipll

Reputation: 11940

One traditional way to solve it is to let the objects clone themselves, plus a bit of CRTP.

I. First, you make your abstract class clonable:

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

Now, every Component should define its own implementation of clone().

II. Which is easily automated via CRTP:

template<class Concrete> struct CompBase: Component {
    Component *clone() const {
        return new Concrete(static_cast<Concrete const &>(*this));
    }
    virtual ~CompBase() {}
};

struct Generator: CompBase<Generator>;  // already has clone() defined

Note that I've used plain pointers in the example, though it is generally recommended to use more smart analogs. std::unique_ptr would fit quite nice, along with std::make_unique.

Which creates another opportunity: with unique_ptr you can even forget about cloning and simply pass unique_ptrs as objects, each one with its own concrete class instance inside, and store them in a vector.

Upvotes: 3

Related Questions