【问题标题】:How to initialize object without default constructor and heap usage?如何在没有默认构造函数和堆使用的情况下初始化对象?
【发布时间】:2021-03-04 13:04:35
【问题描述】:

在没有 MMU 的情况下编写嵌入式系统时,我不应该使用堆(因为内存碎片问题)。

部分软件用C(驱动程序)编写,逻辑用C++子集编写,无需动态分配内存。

由于单元测试,默认构造函数被删除。取而代之的是 - 有一个参考驱动函数指针结构的单参数构造函数。

driver.h:(纯 C 模块)

#pragma once
bool Init();
uint32_t ReadMeasurement();

module.hpp:(C++ 部分)

class Module {
public:
  struct DriverApi {
    void (*Init)();
    uint32_t (*ReadData)();
  };

  Module() = delete;
  explicit Module(DriverApi &aDriverApi);

private:
  DriverApi& mDriverApi;
};

模块管理器:

module_manager.hpp:

class ModuleManager {
//  (...)
private:
  Module::DriverApi module_1; // I can't declare this in this way
  Module::DriverApi module_2; // because of lack of default constructor.
  Module::DriverApi module_3;
  etc.
};

如何在不使用堆的情况下初始化module_1module_2module_3?还有n参数构造函数?

我知道的选项:

  • 看起来很容易使用std::shared_ptr,但后来std::make_shared 使用堆
  • 我可以保留默认构造函数然后调用某事。像 Init(Module::DriverApi *aDriverApi) 但这“违反”RAII

还有其他方法可以创建“优雅”和嵌入式安全初始化吗?

【问题讨论】:

  • 先定义一个DriveApi对象,然后用它来定义Module对象?可以在任何范围内完成。
  • 我不确定我是否理解这个问题。 Module::DriverAPI d; // do stuff with d; Module m(d); 有什么问题?
  • 如果你的类没有默认构造函数,你需要调用另一个构造函数。你能解释一下为什么你认为你需要堆吗? (不清楚您要解决什么问题,更不用说您似乎要解决的问题)
  • mDriverApi 成为参考似乎很奇怪。说的没错,但这确实让我想知道为什么
  • 关于更新的编辑。 Module::DriverApi module_1; 很好。这是一个类成员声明,​​而不是实际定义。那里没有任何东西被初始化。它在ModuleManager 的构造函数中,您实际上是在其中初始化成员。

标签: c++ embedded


【解决方案1】:

要么使用默认构造函数,要么编写带有命名参数的构造函数。如果您需要将成员初始化为非零值,但由于构造函数的参数太少而无法访问这些值,则说明构造函数设计不正确。

由于单元测试,默认构造函数被删除

测试应该让产品变得更好 - 如果他们做相反的事情,就摆脱它们。

通常任何嵌入式系统都有一套固定的驱动程序。因此,通常将它们作为非静态成员毫无意义。为每个硬件外围设备创建一个驱动程序类是有意义的。然后为目标上存在的该硬件的每个实例创建一个static 实例。您不需要涵盖永远不会出现的硬件,硬件也不会在运行时动态更改。事实上,其中很大一部分应该是const 并存储在闪存中。

RAII 在单核、单进程嵌入式系统上的使用有限,因为您的程序需要具有确定性,并且它拥有 MCU 上的所有资源。您通常不需要释放任何东西,您所需要的只是根据产品的需要分配尽可能多的内存。

保持简单。不要发明没有目的的抽象层。

【讨论】:

    【解决方案2】:

    我只是将您的代码放在 IDE 中,然后它就可以编译了。 我可以在您的程序中识别的内容:

    1. 如果您尝试将bool Init(); 分配给void (*Init)(),请更改返回类型。

    2. 定义用户定义的构造函数时,默认构造函数已被隐式删除。缺少的是您必须初始化成员。 试试explicit Module(DriverApi &aDriverApi):mDriverApi{aDriverApi}{}

       class Module {
       public:
           struct DriverApi {
               void (*Init)();
               uint32_t (*ReadData)();
           };
      
           Module() = delete;
           explicit Module(DriverApi &aDriverApi):mDriverApi{aDriverApi}{}
      
       private:
           DriverApi& mDriverApi;
       };
      
      
       void fun(){
           std::cout<<"This is fun\n";
       }
      
       int main(){
      
           Module::DriverApi module_1; // I can't declare this in this way because of lack of default constructor.
      
           module_1.Init = fun;
           module_1.Init();
      
           Module m{module_1};
      
           return 0;
       }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-03
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      • 2012-01-28
      • 2021-12-24
      • 2012-01-02
      相关资源
      最近更新 更多