在串行通信堆栈中使用多态性 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 位是否与给定标识符的预期匹配也是一个好主意。
我正在为 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 位是否与给定标识符的预期匹配也是一个好主意。