嵌入式C++;?ROMable运行时多态性? 我需要在嵌入式C++项目中运行时多态性。在我研究的嵌入式C++最佳实践中,我发现建议在静态内存中声明对象,并且如果不是完全的话,尽量避免动态分配(new /delc/MaloC/Free)。 是我在嵌入式C++中运行时多态性所提出的。其思想是动态分配InterfaceA对象,立即使用它,然后删除它。您不持有该接口类的任何实例。任何持久数据都将从接口类中提取(例如get_index()),并存储在外部。任何时候您需要使用接口功能进行操作,您都可以重新分配接口,立即使用并删除它。这将尽可能避免使用堆
这似乎不是完全最优的。因为我没有在接口中存储任何静态数据,所以我希望有一种静态使用接口的方法 在避免动态分配的同时执行运行时多态性的最佳方法是什么?嵌入式C++;?ROMable运行时多态性? 我需要在嵌入式C++项目中运行时多态性。在我研究的嵌入式C++最佳实践中,我发现建议在静态内存中声明对象,并且如果不是完全的话,尽量避免动态分配(new /delc/MaloC/Free)。 是我在嵌入式C++中运行时多态性所提出的。其思想是动态分配InterfaceA对象,立即使用它,然后删除它。您不持有该接口类的任何实例。任何持久数据都将从接口类中提取(例如get_index()),并存储在外部。任何时候您需要使用接口功能进行操作,您都可以重新分配接口,立即使用并删除它。这将尽可能避免使用堆,c++,polymorphism,embedded,dynamic-memory-allocation,bare-metal,C++,Polymorphism,Embedded,Dynamic Memory Allocation,Bare Metal,这似乎不是完全最优的。因为我没有在接口中存储任何静态数据,所以我希望有一种静态使用接口的方法 在避免动态分配的同时执行运行时多态性的最佳方法是什么? class A { public: int index; int init(int type); } int A::init(int type) { Interface* interface = SelectInterface(type); index = interface->get
class A
{
public:
int index;
int init(int type);
}
int A::init(int type)
{
Interface* interface = SelectInterface(type);
index = interface->get_index(type);
delete interface;
}
好处:有没有办法在保持应用程序(大部分)可读性的同时实现运行时多态性?
class A
{
public:
int index;
int init(int type);
}
int A::init(int type)
{
Interface* interface = SelectInterface(type);
index = interface->get_index(type);
delete interface;
}
然后我有以下界面:
// ----------- INTERFACES -------------- //
class Interface
{
virtual int get_index() = 0;
}
// This is the interface factory
Interface* SelectInterface(int type)
{
if (type == 0)
{
return new InterfaceA();
}
else if (type == 1)
{
return new InterfaceB();
}
return null;
}
class InterfaceA :: public Interface
{
InterfaceA();
int get_index();
}
int InterfaceA::get_index()
{
return 5;
}
class InterfaceB :: public Interface
{
InterfaceB();
int get_index();
}
int InterfaceB::get_index()
{
return 6;
}
运行时多态性、RTTI和动态分配不应用于裸机嵌入式系统应用程序。主要原因是,。但这也是因为嵌入式系统应该始终具有确定性 与其关注您想要使用的语言功能,不如关注应用程序的目的——您试图解决的实际问题——然后相应地设计程序。仅仅为了它而使用语言特性会导致性能瓶颈、元编程、奇怪的bug和代码膨胀
这实际上是C更适合嵌入式系统的主要原因:大多数不应该使用的特性根本不可用。你可以在C++中编写裸露的金属程序,但是它需要广泛的技巧和纪律,知道C++中哪一个限制的子集可以安全地使用。不幸的是,90%的C++程序员都没有能力去做(即使他们自己这么想),所以最好避免C++。p> 正如其他答案和评论中所建议的,我不建议在嵌入式环境中使用动态内存分配。就你有限的记忆而言,有确定性的行为是非常重要的。运行裸机时,很难/不可能捕获内存不足异常。使用RTOS会给您带来更多的灵活性,但不是很多 然而,这是可能的。要使您的程序在没有动态内存分配的情况下具有多态性,您可以使用as of C++11或as of C++17来实现这一点。您可以使用它们来静态分配内存,并在以后初始化实际对象。要支持多个对象,可以使用有限大小的数组 下面的示例为您的接口构造一个静态联合数组。factory函数初始化联合中的内存。clear函数调用析构函数来清除并集
#include <array>
template<int SIZE>
class Buffer
{
private:
union DataUnion
{
// These are required. Please check the documenation of unions.
DataUnion() {};
~DataUnion() {};
// Actual data in the union.
InterfaceA a;
InterfaceB b;
};
std::array<DataUnion, SIZE> dataArray;
public:
Buffer() = default;
~Buffer() = default;
// This is the interface factory
Interface* SelectInterface(int type)
{
// This function will return null when there is no space. You can easily deal with this
// compared to an exception.
Interface* pointer = nullptr;
// First check there is space in the array
// Pseudo code
if(dataArray.has_space())
{
// Pseudo code to get a free union
DataUnion& union = GetFreeUnion();
if (type == 0)
{
// Initialize the memory in the union to be of type A.
// Use the placement new.
new &(union.a) InterfaceA{};
pointer = &(union.a);
}
else if (type == 1)
{
// Initialize the memory in the union to be of type B.
// Use the placement new.
new &(union.b) InterfaceB{};
pointer = &(union.b);
}
}
return pointer;
}
// After your done with the object you need to clear the memory.
void Clear(Interface* pointer_to_data)
{
// Pseudo code to find the index in the array.
int index = FindIndex(pointer_to_data)
DataUnion& union = dataArray[index];
// Pseudo code to retrieve the type stored at that index.
// You need to keep track of that, which is not in this example.
int type = GetType(index);
// Now call the destructor of the object to clear the union.
if(type = 0)
{
union.a.~InterfaceA();
}
else if(type = 1)
{
union.b.~InterfaceB();
}
// Update the administration that index is free.
}
};
// Define the buffer.
Buffer<10> buffer;
main()
{
// Initiate an instance of a.
Interface* pA = buffer.SelectInterface(0);
if(nullptr != pA)
{
// Do something.
}
// Initiate an instance of b.
Interface* pB = buffer.SelectInterface(1);
if(nullptr != pB)
{
// Do something.
}
// Stop using a.
buffer.Clear(pA);
// And on
}
#包括和此李>
您需要实现代码来跟踪哪些索引被占用
此时,我还没有使用std::variant选项。我想这会更简单,因为您不需要手动初始化和清除内存
我希望这能回答你的问题。是的,可以使用多态性和静态分配
<>如果你正在寻找更多的例子,说明如何在嵌入式设备中使用C++,你可以看看代码。我发现它非常清楚C++代码(我的观点),我发现ARM是世界上最大的MCU设计者之一,已经选择C++作为代码。它们会分散实际问题的注意力,并引发类似这样的评论。您可以将接口实现存储在全局变量中,并让SelectInterface
返回指向全局变量的指针或引用。(从来没有使用嵌入式处理器的PC程序员听到了一个令人不安的事实:C++不适合他们自己从未工作过的分支。而我已经编程了C++和嵌入式系统将近20年。)——1,我为一家小公司做了专业的嵌入式程序。(与我的同事和上司的意见相反)8位控制器的项目是C++。回顾一下,这是正确的决定。它允许我编写更稳定的代码。我确实重写了大部分公司代码,这是一个混乱,后来它工作了。是的,我没有使用堆分配,或者是由C++ OOP提供的可怜的多态性。你必须知道你在做什么,我同意。我同意你的回答。但是说嵌入式项目最好用C语言编程是完全错误的。@ziggystar所以你是提到的10%之一,祝贺你。你的同事可能不是。然后他们可能不得不在你之后维护这个项目。有了一个成熟的符合标准的编译器,这意味着他们可以自由添加RTTI,例外是h从主流编程资源中学习C++的人们可能会得到安顿、堆分配或其他任何坏主意。因为在C堆分配中不可能实现。@ ZigGISAR它们是完全可能的,但是在C中,它并不是秘密隐藏在标准的LIBs内,例如在STD::vector或STD::string中。