Итак, вам понадобится какой-то указатель. A std::shared_ptr
работает хорошо:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
Имейте в виду, что PInstruction подсчитывается по ссылке, поэтому конструктор копирования PInstruction создаст новую «ссылку» на тот же объект.
Если вы хотите сделать копию ссылочного объекта, вам придется реализовать метод clone:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
Если производительность является проблемой, чем вы можете посмотреть на std::unique_ptr
, это немного сложнее управлять, поскольку семантика перемещения всегда требуется, но она позволяет избежать затрат на некоторые атомные операции.
Вы также можете использовать необработанные указатели и управлять памятью вручную с помощью какой-либо архитектуры пула памяти.
Основная проблема заключается в том, что для получения полиморфного типа компилятор не знает, насколько велики будут подклассы, поэтому вы не можете просто иметь вектор базового типа, так как он не будет иметь дополнительное пространство, необходимое для подклассов. По этой причине вам нужно будет использовать семантику pass-by-reference, как описано выше. Это сохраняет указатель на объект в векторе, а затем сохраняет объект в куче в блоках разных размеров в зависимости от того, что требуется подклассу.