gpt4 book ai didi

c++ - 使开关繁重的功能更具可重用性

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

假设我有这段代码:

void ClassA::SomeFunction()
{
switch(something)
{
case case1:
doSomething();
break;
case case2:
doSomethingElse();
break;
.
.
.
}
...
void ClassB::SomeFunction()
{
switch(something) // this 'something' is the same 'something' as in
{ // the above class
case case1:
doSomethingCompletelyUnrelatedToClassAFunction();
break;
case case2:
doSomethingCompletelyUnrelatedToClassAOtherFunction();
break;
.
.
.
}

两个类中的两个函数在完全相同的情况下做完全不同的事情(两个开关中的所有情况都完全相同)。基本上我是为了好玩而编写一个小型 Chip-8 仿真器,这两个类代表我的“CPU”和反汇编程序。

CPU 应该解码操作码并做一些事情,而反汇编器应该简单地根据操作码格式化字符串。

我正在尝试想出一种方法来避免复制/粘贴整个开关,而只是更改在每种情况下调用的函数。

我想出的一个简单解决方案是创建一个抽象类来处理操作码,并对开关中的每种情况使用不同的方法。 CPU 和 Disassembler 类都将扩展此类并为每个方法实现它们自己的行为。但是,我希望有一个比这更优雅的解决方案。

谢谢。

编辑:

根据@Dogbert 的评论,我添加了一大块实际代码:

wxString* DebugWindow::DisassembleOpCode(uint16_t opCode)
{
wxString disLine;

uint8_t nibble1 = (opCode & 0xF000) >> 12;
uint8_t nibble2 = (opCode & 0x0F00) >> 8;
uint8_t nibble3 = (opCode & 0x00F0) >> 4;
uint8_t nibble4 = (opCode & 0x000F);

if (opCode == 0x00E0)
disLine = "CLS";
else if (opCode == 0x00EE)
disLine = "RET";
else
switch (nibble1)
{
case 0x1:
{
// JMP nnn
disLine = wxString::Format("JMP %04x", nibble2 | nibble3 | nibble4);
break;
}
case 0x2:
{
// CALL nnn
disLine = wxString::Format("CALL %04x", nibble2 | nibble3 | nibble4);
break;
}
case 0x3:
{
// SE V[x], nn -- skip next instruction if V[x] == nn
disLine = wxString::Format("SE V[%x], %02x", nibble2, nibble3 | nibble4);
break;
}

...
...
...

case 0x8: // arithmetic operations between registers, see below
{
switch (nibble4)
{
case 0x0:
{
// LD V[x], V[y] -- sets value of register V[x] to value of register V[y]
disLine = wxString::Format("ADD V[%x], V[%x]", nibble2, nibble3);
break;
}
case 0x1:
{
// OR V[x], V[y] -- performs bitwise OR of values of registers V[x] and V[y], the result is stored in V[x]
disLine = wxString::Format("OR V[%x], V[%x]", nibble2, nibble3);
break;
}

...
...

这是 DisassembleOpcode 函数的一部分。 CPU 类中的 Step 函数实际上应该做一些事情而不是格式化字符串,但它由相同的开关/案例组成。

最佳答案

在 C 中,您可以用函数指针数组替换开关。在 C++ 中,您还有一个额外的选择,即使用指向具有多态行为的类的指针。

以下是使用函数指针的方法:

typedef void (*disassembly_action)(uint8_t,uint8_t,uint8_t,uint8_t);

static void doSomethingOpcodeZero(uint8_t,uint8_t,uint8_t,uint8_t);
static void doSomethingOpcodeOne(uint8_t,uint8_t,uint8_t,uint8_t);
static void doSomethingOpcodeTwo(uint8_t,uint8_t,uint8_t,uint8_t);
static disassembly_action disassembly[] = {
doSomethingOpcodeZero
, doSomethingOpcodeOne
, doSomethingOpcodeTwo
, ...
};

现在您可以使用数组索引代替开关:

void ClassA::SomeFunction() {
uint8_t nibble1 = (opCode & 0xF000) >> 12;
uint8_t nibble2 = (opCode & 0x0F00) >> 8;
uint8_t nibble3 = (opCode & 0x00F0) >> 4;
uint8_t nibble4 = (opCode & 0x000F);
disassembly_action[something](nibble1, nibble2, nibble3, nibble4);
}

您可以构建一个类似的数组来替换其他 switch,也许对您的 action 函数使用不同的签名。

关于c++ - 使开关繁重的功能更具可重用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22996311/

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