Вот моя проблема, упрощенно:
enum AnimalType_t { СОБАКА = 0, GREY_HOUND = 1, IMMORTAL_JELLYFISH = 2, }; struct RawData_t { в возрасте; AnimalType_t typeOfAnimal; }; RawData_t GetMyCurrentRawData (); // возвращает текущие необработанные данные bool IsDataReady (); // возвращает true, если данные готовы, иначе false
класс животных { общественности: виртуальное животное (); виртуальный ~ Animal (); int GetType () {return rawAttributes.typeOfAnimal; }; // единственная реализация для всех детей virtual int GetAge () {return rawAttributes.age; }; // для реализации в дочернем классе виртуальная пустота UpdateAge () {rawAttributes.age ++; }; // для реализации в дочернем классе virtual int GetNumberOfLegs () = 0; // для реализации в дочернем классе частный: RawData_t rawAttributes; }
класс собака: общественное животное { общественности: Собака (RawData rawData): Животное (rawData) {}; int GetNumberOfLegs () {return 4;}; }; класс GreyHound: публичный пёс { общественности: GreyHound (RawData rawData): Dog (rawData) {}; }; класс ImmortalJellyFish: общедоступное животное { общественности: ImmortalJellyFish (RawData rawData): Animal (rawData) {}; int GetNumberOfLegs () {return 0;}; void UpdateAge () {return;} переопределить; };
Здание класса { общественности: Строительство(){}; // простите за длинную очередь, но вы поняли идею ... int Display (void) {if (IsDataReady ()) DisplayOnScreen ("Это животное (" + animal_m.GetType () + ") имеет" + animal_m.GetNumberOfLegs () + "ноги и является" + animal_m.GetAge () + ") лет \ n ";}; int Live (void) {currentDiagCode_m.UpdateAge ();}; частный: auto animal_m; // ?? не работает }; статический строительный загон; статичное здание фермы; void Buildings_Step (void) { paddock.Live (); paddock.Display (); farm.Live (); farm.Display (); }
Вот где я борюсь:
Вот мои ограничения:
Я хоть о:
Есть ли дизайн / модель, которая может удовлетворить мои потребности?
Спасибо!
В 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
вместо. Это концептуально схожий, но несколько иной подход к реализации. Причина, по которой это концептуально схоже, заключается в том, что у вас есть ограниченный набор типов, поэтому вам не нужен полиморфизм для обработки произвольно, неизвестно производные типы во время выполнения.
Других решений пока нет …