В C ++ распределение памяти и существование объекта - это две разные концепции, хотя в большинстве ситуаций вы будете обрабатывать обе вместе.Однако в вашем случае вы можете явно разделить их:
Создать достаточно памяти для любого объекта:
char buf[N]; // N >= sizeof(T) for all T in your hierarchy
Длясоздать животное:
new (buf) GreyHound(args);
Чтобы уничтожить существующее животное (и освободить место для другого):
reinterpret_cast<Animal*>(buf)->~Animal();
То естьвы получаете хранилище как часть вашего контейнерного объекта, но вы динамически управляете временем жизни объекта Animal с новым размещением и явным уничтожением.
Есть еще кое-что: ваша память также должна быть правильно выровнена для всех типовчто вы в нем строите.Вы можете использовать некоторые вспомогательные черты библиотеки, такие как std::aligned_storage
или std::aligned_union
, чтобы упростить вычисления, хотя вам, вероятно, все равно потребуется немного поработать, чтобы вычислить как размер, так и выравнивание.
В качестве совершенно отдельной альтернативы вы можете отказаться от полиморфной иерархии классов и использовать вместо нее std::variant
.Это концептуально схожий, но несколько иной подход к реализации.Причина, по которой это концептуально схоже, заключается в том, что у вас ограниченный набор типов, поэтому вам не нужен полиморфизм для обработки произвольных, неизвестных производных типов во время выполнения.