在串行通信堆栈中使用多态性 C++

Using polymorphism in serial communication stack c++

我正在为 STM32 微控制器编写基于 mbed 库的自定义高层 CAN 串行通信协议。

我已经定义了将在协议中使用的大约 2 打消息。一些消息是分段的(即 3 条单独的消息,可能按顺序出现,也可能不按顺序出现)。

目前我有一个很大的 switch 语句,用于根据消息 ID 处理传入的消息,它看起来像这样:

switch (msgID){
    case END_CHARGE_REPORT_1_MSG:
        return processEndChargeReportMsg(msgID);
    case END_CHARGE_REPORT_2_MSG:
        return processEndChargeReportMsg(msgID);
    case END_CHARGE_REPORT_3_MSG:
        return processEndChargeReportMsg(msgID);
    case END_CHARGE_REQUEST_MSG:
        return processEndChargeRequestMsg(msgID);

    case START_CHARGE_REPORT_1_MSG:
        return processStartChargeReportMsg(msgID);
    case START_CHARGE_REPORT_2_MSG:
        return processStartChargeReportMsg(msgID);
    case START_CHARGE_REPORT_3_MSG:
        return processStartChargeReportMsg(msgID);

然后在每个处理函数中,我检查是否已接收到分段消息组中的所有消息,parse/format 消息数据,使用该数据作为调用与接收到的消息对应的函数的参数。

我觉得有一种 better/cleaner/faster 方法可以用多态性来做到这一点,但我似乎不知道该怎么做。

我想要这样的东西:

class myCANMessages{
    virtual process()
}

//Derived classes for each type of message group
class startChargeMessageGroup : public myCANMessages{
    CANMessage fullMsgGroup[3];
    process(){
          load CANMessage into fullMsgGroup
          if(allMessagesReceived)
                 parse(CANMessage)
                 take_action(decoded data from CANMessage)
    }
}

class endChargeMessageGroup : public myCANMessages{ ///etc...etc...

然后继续处理传入的 CAN 消息(将索引保存到缓冲区中的相关 CAN 消息,在接收到所有消息时解析它们,使用接收到的数据作为参数调用相应的函数),结构如下:

myCANMessages *polymorphPointer

while(1){
 CANMessage = readCANMessage();

--> somehow assign this automagically to correct derivedObject type


polymorphPointer = &derivedObject;
polymorphPointer->process


}

..虽然不太明白...d'oh!

您可以将 "CAN message" 作为抽象基础 class,然后为每个唯一的 CAN 标识符继承它。但这对我来说听起来有点矫枉过正。

通常我通过查找 table 来解决这些情况,按标识符排序。 table 中的每一项都包含一个支持的标识符和一个函数指针。 (从本质上讲,这就是多态性无论如何都会归结为的。)

收到消息后,您通过 table 进行二进制搜索以查看是否支持该标识符。如果是,则调用该函数。

基本上是这个伪代码:

CAN_msg msg = can_read();
const CAN_msg* supported = binary_search(table, msg.id);
if(supported) 
{
  supported->process();
}

始终检查大小 (DLC) 和 RTR 位是否与给定标识符的预期匹配也是一个好主意。