gpt4 book ai didi

c++ - 如何在 C++ 中定义一个制作精良的消息类

转载 作者:太空狗 更新时间:2023-10-29 20:52:20 24 4
gpt4 key购买 nike

目前我正在使用 C++ 编写一个用于数据通信的消息类,例如通过串行端口。对于这个问题,假设我有两条不同的消息(我确实有更多),例如带有校准数据和传感器值的陀螺仪和加速度消息。由于我是一名自学 C++ 的工程师,所以我看了我最喜欢的 C++ 书籍,发现对消息使用工厂模式可能会有用。

所以我的头文件的简化版本如下所示:

#ifndef MESSAGE_H
#define MESSAGE_H
#include <cstddef>

class message
{
public:

/**
* \brief ~message:
* Virtual destructor of the class message.
*/
virtual ~message();

/**
* \brief getMessage:
* Creates a message (with new).
*
* \param[in] size Size of the dataArray.
* \param[in] data Bytearray of the message.
*
* \return If messagetype in the Array data eqal to 0 => new GyroMessage.
* If messagetype in the Array data eqal to 1 => new AccelMessage.
* Else => new NotValidMessage.
*
*/
static message* getMessage(size_t size, char* data);

protected:

/**
* \brief message:
* Default konstructor of the class message.
*
* \param[in] size Size of the dataArray.
* \param[in] data Bytearray of the message.
*
*/
message(size_t size, char* data);

/// Size of the dataArray.
int size;
/// Bytearray of the message.
char* dataArray;
/// Type of message.
char messagetype;
};

#endif // MESSAGE_H

GyroMessageAccelMessageNotValidMessagemessage 的子类。这种模式有两点我不喜欢:

首先:如果我想添加一条新消息,现在添加一个继承自 message 的新类就足够了,您必须在静态函数中添加另一个 if 语句 getMessage.

第二:如果我想使用数据,例如从 GyroMessage,我必须reinterpret_cast 消息。

是否有更好的模式可用于此目的?

最佳答案

我不确定我的想法是否好,但分享不需要任何费用。

我几天前为 Arduino 做了类似的事情,对于我的情况,我做出了这样的选择:

  • 对我来说,数据有效负载是一个 pod(普通旧数据)结构,编译器会在其中打包它。为此,我使用了一个 define 来处理编译器指令以将其打包(对于 g++__attribute__((packed)))
  • 在我的例子中,这个类处理几乎所有的事情,因此我用一个模板来编写它。该模板用于有效负载结构
  • 为了在字节数组中发送消息,我在类中使用了模板化的union。如果使用此方法,则必须检查发送方和接收方的字节顺序。类似的东西:

    template <class P>
    union Packet {
    P data;
    unsigned char buff[sizeof(P)];
    }

    我的工具链支持模板,所以我使用了它们。但是您可以使用更多模板在同一个 union 中插入更多包。您只需要记住在标识包类型的所有结构中都有一个公共(public)字段(见下文)。

  • 我的类不处理读取和写入,而是要求类的用户提供 2 个读取和写入回调,接受缓冲区本身、缓冲区的维度和用户数据的 void 指针作为参数。我认为这是使类与传输 channel 无关的好方法。

例子(我简化了很多):

template <class A, class B,  std::size_t N>
union Packet {
A a;
B b;
unsigned char buffer[N];
};

#define PAYLOAD(X, Y) struct X \
Y __attribute__((packed)); \
typedef struct X X;

template <class A, class B, std::size_t N>
class Message {
union Packet<A, B, N> packet;

// [...]
}

// [...]

// Time to declare you messages
PAYLOAD(GyroMessage, { char type; float x; float y; })
PAYLOAD(AccelMessage, { char type; float x; float y; float z; })
// GyroMessage will always have type = 0x01 and
// AccelMessage will always have type = 0x02 for example

// you know that sizeof(AccelMessage) > sizeof(GyroMessage)
// there is for sure a way to automatize this thing at
// compilation time through macros.
// Time to declare the class
Message<GyroMessage, AccelMessage, sizeof(AccelMessage)> message;

要检索正确的值,您仍然可以(通过 union )访问所需的值,而无需添加新的特定函数。但目前我没有非常好的方式以编程方式访问它们。

那些只是一些提示,我真的不知道你在做什么或者你的优先级是什么。因此,请谨慎服用。

关于c++ - 如何在 C++ 中定义一个制作精良的消息类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46401734/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com