Reputation: 5339
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
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