Here's my issue, simplified:
- I have a code in C/C++, C for services, C++ for handling.
- I have an interface in C that returns a structure RawData that contains information which is cyclically updated.
enum AnimalType_t
{
DOG = 0,
GREY_HOUND = 1,
IMMORTAL_JELLYFISH = 2,
};
struct RawData_t
{
int age;
AnimalType_t typeOfAnimal;
};
RawData_t GetMyCurrentRawData();//returns the current raw data
bool IsDataReady(); //returns true if data is ready, false otherwise
- I have a virtual mother class "Animal"
class Animal
{
public:
virtual Animal();
virtual ~Animal();
int GetType() { return rawAttributes.typeOfAnimal; }; //the only implementation for all children
virtual int GetAge() { return rawAttributes.age; }; //to be implemented in the child class
virtual void UpdateAge() { rawAttributes.age++; }; //to be implemented in the child class
virtual int GetNumberOfLegs() = 0; //to be implemented in the child class
private:
RawData_t rawAttributes;
}
- I have a known list of animals which inherit from the mother class.
class Dog : public Animal
{
public:
Dog(RawData rawData):Animal(rawData){};
int GetNumberOfLegs() {return 4;};
};
class GreyHound : public Dog
{
public:
GreyHound(RawData rawData):Dog(rawData){};
};
class ImmortalJellyFish : public Animal
{
public:
ImmortalJellyFish(RawData rawData):Animal(rawData){};
int GetNumberOfLegs() {return 0;};
void UpdateAge() { return;} override;
};
- I have a class "Building" in which there is one, only one, animal but I don't know its type when I instantiate the building.
class Building
{
public:
Building(){};
//sorry for the long line, but you get the idea...
int Display(void){if(IsDataReady()) DisplayOnScreen("This animal ( "+ animal_m.GetType()+") has " + animal_m.GetNumberOfLegs() + "legs and is " + animal_m.GetAge() + " years old\n";};
int Live(void){currentDiagCode_m.UpdateAge();};
private:
auto animal_m; //?? not working
};
static Building paddock;
static Building farm;
void Buildings_Step(void)
{
paddock.Live();
paddock.Display();
farm.Live();
farm.Display();
}
Here's where i'm struggling:
- allocate memory for an animal in a Building without knowing its type during building instantiation,
- type and attributes of the animal might change cyclically In other words: is dynamic typing with static allocation possible? Then, how can I call these instances so the right method is called?
Here're my constraints:
- embedded system
- no dynamic memory allocation
I though about :
- factory design pattern with unique_ptr which works great!!!... but, on the heap :(
- Object Pool?
- dynamic typing: but non possible without dynamic allocation, is it?
Is there any design/model that could fulfill my needs?
Thank you!
In C++, memory allocation and object existence are two separate concepts, even though in most situations you'll handle both together. In your case, though, you may wish to explicitly separate the two:
Create enough memory for any object:
To create an animal:
To destroy an existing animal (and make room for another):
That is, you obtain storage as part of your container object, but you manage the Animal object lifetime dynamically with placement-new and explicit destruction.
There's a bit more to this: your memory also needs to be aligned correctly for all types that you construct in it. You can use some library helper traits like
std::aligned_storageorstd::aligned_unionto simplify the computation, though you'll probably still need to do a bit of work to compute both the size and the alignment.As a completely separate alternative, you could forego the polymorphic class hierarchy and use a
std::variantinstead. This is conceptually similar, but a somewhat different approach implementation-wise. The reason that this is conceptually similar is because you have a bounded set of types, so you don't really need polymorphism to handle arbitrary, unknown derived types at runtime.