嵌入式 C++:没有动态分配的动态类型?
embedded c++ : dynamic typing without dynamic allocation?
这是我的问题,经过简化:
- 我在 C/C++ 中有一个代码,C 用于服务,C++ 用于处理。
- 我在 C 中有一个接口,returns 一个包含循环更新信息的结构 RawData。
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
- 我有虚拟妈妈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;
}
- 我有一份已知的从母亲那里继承的动物列表 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;
};
- 我有一个 class "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();
}
这是我挣扎的地方:
- 在建筑物实例化期间为建筑物中的动物分配内存,而不知道其类型,
- 动物的类型和属性可能会周期性变化
换句话说:静态分配的动态类型是否可能?
那么,我怎样才能调用这些实例以便调用正确的方法呢?
这是我的限制条件:
- 嵌入式系统
- 没有动态内存分配
我想:
- 具有 unique_ptr 的工厂设计模式非常有效!!!......但是,在堆上 :(
- Object游泳池?
- 动态类型:但是没有动态分配是不可能的,是吗?
有什么design/model可以满足我的需求吗?
谢谢!
在 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
来简化计算,但您可能仍需要做一些工作来计算大小和对齐方式。
作为一个完全独立的替代方案,您可以放弃多态 class 层次结构并改用 std::variant
。这在概念上是相似的,但在实现方面有些不同。这在概念上相似的原因是因为你有一组有限的类型,所以你真的不需要多态性来在运行时处理任意的、未知的派生类型。
这是我的问题,经过简化:
- 我在 C/C++ 中有一个代码,C 用于服务,C++ 用于处理。
- 我在 C 中有一个接口,returns 一个包含循环更新信息的结构 RawData。
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
- 我有虚拟妈妈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; }
- 我有一份已知的从母亲那里继承的动物列表 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; };
- 我有一个 class "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(); }
这是我挣扎的地方:
- 在建筑物实例化期间为建筑物中的动物分配内存,而不知道其类型,
- 动物的类型和属性可能会周期性变化 换句话说:静态分配的动态类型是否可能? 那么,我怎样才能调用这些实例以便调用正确的方法呢?
这是我的限制条件:
- 嵌入式系统
- 没有动态内存分配
我想:
- 具有 unique_ptr 的工厂设计模式非常有效!!!......但是,在堆上 :(
- Object游泳池?
- 动态类型:但是没有动态分配是不可能的,是吗?
有什么design/model可以满足我的需求吗?
谢谢!
在 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
来简化计算,但您可能仍需要做一些工作来计算大小和对齐方式。
作为一个完全独立的替代方案,您可以放弃多态 class 层次结构并改用 std::variant
。这在概念上是相似的,但在实现方面有些不同。这在概念上相似的原因是因为你有一组有限的类型,所以你真的不需要多态性来在运行时处理任意的、未知的派生类型。