我遇到了一个问题,无法找到易于维护且易于阅读的解决方案。
我基本上是在写“主状态机” 我有一个节点,它从其他3个从属节点接收枚举,这些从属节点独立地执行其操作并进入特定状态并将其报告给主节点。
从站1输出枚举之一:
enum slave1 {
A,
B
}
从站2输出枚举之一:
enum slave2 {
1,
2
}
从站3输出枚举之一:
enum slave3 {
a,
b,
c
}
请务必注意,我对从属节点的行为,结构和输出没有任何控制权
现在,基于接收到的值,我的主节点具有以下逻辑
val_slave_1 = getSlave1Val();
val_slave_2 = getSlave2Val();
val_slave_3 = getSlave3Val();
switch(val_slave_1):
case A:
switch(val_slave_2):
case 1:
switch(val_slave_3):
case a: {do Z}
case b: {do Y}
case c: {do X}
case 2:
switch(val_slave_3):
case a: {do W}
case b: {do V}
case c: {do U}
case B:
switch(val_slave_2):
case 1:
switch(val_slave_3):
case a: {do T}
case b: {do S}
case c: {do R}
case 2:
switch(val_slave_3):
case a: {do Q}
case b: {do P}
case c: {do O}
此代码的优点是-
此代码的问题是它-
我对大家的问题是,有没有更好的方法?我读过很多地方说多态性通常是解决switch语句的好方法,但是我试图使我的代码具有多态性,但似乎无法确定解决方案。虽然很多人都给出了一些简单的例子,例如车辆和猫,但我似乎无法将其应用于我的问题。
另一个重要说明:显而易见,但我仍然会写。编写switch case语句的顺序无关紧要。为了保持理智,我将选择按最大到最小枚举的顺序编写它,以节省代码行(我认为)
我找到的最接近该问题的线程是-
Is there any design pattern to avoid a nested switch case?
但是有比维护枚举字典映射到函数更好的方法吗?
答案 0 :(得分:1)
由于枚举值很小,因此从枚举组合到函数的映射可能只是一个数组。当您具有3、4和7个值(分别为2、2和3位)时,可以使用单个字节索引到函数指针数组中。像这样:
using Handler = void (*)();
std::array<Handler, 128> handlers = { doA, doB, doB, doG, nullptr, ..., doFoo };
int v1 = slave1(); // 0-6
int v2 = slave2(); // 0-3
int v3 = slave3(); // 0-2
int index = (v2 << 5) | (v1 * 3 + v3);
handlers[index]();
如果您的枚举值从0到n不连续,则可能必须将它们重新映射到该值。
您可能想提出一种聪明的填充数组的方法,因为在某些更改可能需要一段时间后才能手动重新计算索引。我现在可以想到的一种方法是constexpr
函数,该函数采用许多结构,每个结构均包含枚举值和函数指针,并从中填充一个数组。结构将计算索引,函数将仅从索引分配函数指针。或类似的东西。