在嵌入式系统中不使用堆的 C++ 组合

C++ composition without using the heap in embedded systems

我是 C++ 的新手,这也是我的第一个 post。我正在尝试在嵌入式系统项目中使用 C++,以便采用 OOP 方法。我正在使用 AVR crosspack 工具链(AVR G++ 编译器)

我的问题是:

根据我的阅读,堆不应该用于嵌入式系统中的动态内存分配。无论如何,在 AVR G++ 中无论如何都没有“新”的实现。我正在使用组合,从一个 USART 驱动程序(我们称之为服务)和一个记录器(单例模式,也是一个服务)开始。

据我了解,服务应该使用构造函数参数在实例化时传递它们的依赖关系,但是当我尝试以这种方式组合所需的对象时,出现以下错误:

Main/main.cpp: In function 'int main()':
Main/main.cpp:21:13: error: request for member 'log' in 'logSystem', which is of non-class type 'LogSystem(Usart)'
   21 |   logSystem.log("Hello");
      |             ^~~
make: *** [Main/main.o] Error 1

我的感觉是我将对象作为构造函数参数传递的语法是错误的,但我不确定它应该是什么,因为我能找到的所有示例都在构造函数定义中使用“new”关键字在免费商店上创建对象。有人可以帮忙吗?

代码:

在“usart.h”中:

#include <avr/io.h>
#include <util/setbaud.h>

class Usart
{
public:
  // Constructor and destructor
  Usart();
  ~Usart();

  // Initialisation routine
  static void const init(void);

  // Utility function to transmit a string
  static void const print(const char myString[]);
};

在“logger.h”中:

#include "usart.h"

class LogSystem
{
public:

  LogSystem(Usart usart);
  ~LogSystem();

  Usart usart;

  static void const log(char *msg);

};

在“logger.cpp”

#include "logger.h"

LogSystem::LogSystem(Usart usart)
{
  Usart usart;
  usart.init();
}

LogSystem::~LogSystem()
{
}

LogSystem::log(char *msg)
{
  usart.print(msg);
}

在“main.cpp”中:

#include "logger.h"


int main()
{
    LogSystem logSystem(Usart usart);

    while(1)
    {
        logSystem.log("Hello");
    }

    return 0;
}

[...] the heap should not be used for dynamic memory allocation in embedded systems.

视情况而定。我目前在一个具有最高安全相关要求的嵌入式项目中,我们使用 new,但不使用 delete。所以我们有一个堆,但不要“动态”分配,因为所有分配的对象都在运行时保留。

In any case, there is no implementation for "new" in AVR G++ anyway.

这是真的吗?我从未检查过...在能够使用 new.

之前可能需要提供一个堆

It's my understanding that services should have their dependancies passed in on instantiation using constructor parameters, [...]

这是个好主意。 ;-) 它有助于单元测试。

对于您的语法和设计问题:这就是我编写您的来源的方式。

"usart.h":

所有方法都是非静态的,可以访问成员变量。

return 类型的 const 属性没有任何作用。您是要声明方法常量吗?然后 const 属于参数列表之后。但是,如果这样的方法更改任何成员变量,则此属性可能是错误的。

#include <avr/io.h>
#include <util/setbaud.h>

class Usart
{
public:
  Usart();
  ~Usart();

  void init(void);

  void print(const char myString[]);
};

"logger.h":

只需提供并存储对 USART 的引用即可避免复制。

#include "usart.h"

class LogSystem
{
public:
  LogSystem(Usart& usart);
  ~LogSystem();

  void log(const char *msg);

private:
  Usart& _usart;
};

"logger.cpp"

成员变量_usart直接在构造函数中初始化,在执行任何语句之前。

#include "logger.h"

LogSystem::LogSystem(Usart& usart) : _usart(usart)
{
  _usart.init();
}

LogSystem::~LogSystem()
{
}

void LogSystem::log(const char *msg)
{
  _usart.print(msg);
}

"main.cpp":

在堆栈上提供 USART 对象,作为记录器。

#include "logger.h"

int main()
{
    Usart usart;
    LogSystem logSystem(usart);

    while(1)
    {
        logSystem.log("Hello");
    }

    return 0;
}

单例设计模式自发明以来就被弃用了,因为它太难测试了。只需使用一个对象或限制对象工厂。