c++ - 在 vector 中调用函数指针不会做任何事情

标签 c++ function-pointers

我目前正在尝试实现 CHIP-8 仿真器。在这些仿真器中,您可以读取盒式磁带的内容,它会为您提供“操作码”,即与函数对应的值。我不想写一个巨大的 switch case 语句来处理这些操作码(在 CHIP-8 模拟器的上下文中,这没问题,因为没有太多的操作码,但在​​上下文中Gameboy 模拟器,例如,它可以产生一些巨大的 switch case 语句)。

我的做法如下:

我有一个包含操作码范围、函数名称和函数指针的结构 (void* func)。

struct instruction {
    std::pair<uint16_t, uint16_t> range;
    std::string name;
    void* func;

    instruction(std::pair<uint16_t, uint16_t> range, std::string name, void* func) {
        this->range = range;
        this->name = name;
        this->func = func;
    }
};

我的类看起来像这样(请不要打我,我现在把所有东西都放在 public 上,但是当一切正常时,一切都会变成私有(private)的):

class Chip8 {
    public:
        Chip8();
        virtual ~Chip8();

        void set_opcodes(void);

        bool load_cartridge(std::string path);
        void output_cartridge_contents(void);
        bool verifiy_instructions(void);

        void JUMP(void);

        // 0     -> 0x1FF: interpreter (unused since the emulator is running outside of the memory)
        // 0x200 -> 0xE9F: cartridge data
        // 0xEA0 -> 0xEFF: call stack, internal use, and other variables
        // 0xF00 -> 0xFFF: display refresh
        std::vector<uint8_t> memory;
        std::vector<uint8_t> registers;

        // Index register
        uint16_t I;
        // Program counter
        uint16_t pc;

        std::vector<uint8_t> stack;
        // Stack pointer
        uint8_t sp;

        std::vector<instruction> instr;

        // Timers
        uint8_t delay_timer;
        uint8_t sound_timer;

        uint16_t opcode;

        // Screen
        bool gfx[64 * 32];

};

让我们举个例子,JUMP

void Chip8::JUMP(void) {
    this->pc = (this->opcode & 0x0FFF);
}

然后我将填充一个包含所有已实现操作码的 vector ,

this->instr.push_back(instruction(std::pair<uint16_t, uint16_t>(0x1000,0x1FFF), std::string("JUMP"), (void*)&Chip8::JUMP))

读取当前操作码,然后与实现函数的范围进行比较(例如,如果操作码是0x1225,将调用JUMP 函数)。找到正确的函数后,将调用以下代码(i 是上面显示的 instr vector 中正确的 instruction 的索引):

this->instr[i].func;

但是当我这样做时,什么也没有发生(即 pc 的值没有改变,std::cout 在控制台上什么也不产生,等等)。我尝试了多种方法(将 func 类型更改为 void (*func)(void),尝试调用 this->instr[i].func( );), 但到目前为止运气不好。我想我在这里遗漏了一些东西。有人有一些指示吗?

谢谢

最佳答案

由于 Chip8::JUMP 是一个非静态类成员函数,您需要一个类的对象来调用该函数。这是因为非静态成员函数具有类类型的隐式第一个参数,用于在函数内部启用 this 的使用。

您可以通过使用 std::function 并使用 lambda 或 std::bind 将函数绑定(bind)到对象来解决此问题。看起来像

struct instruction {
    std::pair<uint16_t, uint16_t> range;
    std::string name;
    std::function<void(void)> func;

    template<typename Func>
    instruction(std::pair<uint16_t, uint16_t> range, std::string name, Func func) : range(range), name(name), func(func) {}
};

//...

this->instr.push_back(instruction(std::pair<uint16_t, uint16_t>(0x1000,0x1FFF), std::string("JUMP"), [this]{ this->JUMP(); }))

// and call it like

this->instr[i].func();

关于c++ - 在 vector 中调用函数指针不会做任何事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55477156/

相关文章:

c++ - 如何在 Windows XP 下从 Dev-c++ 中获取预处理代码?

c++ - 弃用 Typedef

c++ - 解析C++的句法结构是否比其他语言更难?

c++ - 使用 GUI 和工作线程提升 Asio 模式

c++ - 如何在不在 C++ 中创建函数对象的情况下将函数指针作为模板值参数传递?

c++ - 通过右值引用返回 lambda?

c++ - 如何在STL中调​​用函数指针

c++ - 为什么将函数名用作函数指针等同于将寻址运算符应用于函数名?

通过main调用另一个函数来打开文件

c++ - 通过函数指针计算的 goto/jump 与 fastcall 哪个成本更高?