嵌入式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中。