调用成员函数指针时指向与对象不兼容的成员类型指针

Pointer to member type incompatible with object when calling member function pointer

问题

我有一个在 运行 时分配的成员函数指针数组。尝试调用它们时出现编译时错误:

pointer to member type 'void (YCPU::)(uint16_t)' {aka 'void (YCPU::)(short unsigned int)'} incompatible with object type 'YCPUInstruction'`

我无法理解调用指针的正确语法。

代码和问题详情

我有一个存储两个成员函数指针的结构YCPUInstruction。这些函数指针指向YCPU内部的成员函数。我存储了一个 YCPUInstructions 的数组,在初始化期间我调用了 initialize,它将这些指针分配给正确的成员函数。

成员函数指针和YCPU指令:

typedef void (YCPU::*YCPUOpcode)(uint16_t opcode);
typedef std::string (YCPU::*YCPUDisassembler)(std::string name, uint16_t operand, uint16_t nextword, uint16_t address,
                                              bool show_memory_contents, uint16_t &instruction_size);


struct YCPUInstruction {
    std::string name;

    static YCPUOpcode opcode;
    static YCPUDisassembler disassembler;

    int cycles;
    bool is_nop;

    void initialize(std::string name, YCPUOpcode opcode, YCPUDisassembler disassembler, int cycles, bool is_NOP = false)
    {
        this->name = name;
        this->opcode = opcode;
        this->disassembler = disassembler;
        this->cycles = cycles;
        this->is_nop = is_NOP;
    }
};

YCPU

class YCPU
{
public:
    // YCPUOpcode points to one these functions (many more than these 3, just examples)
    void NOP(uint16_t opcode);
    void ADC(uint16_t opcode);
    void ADD(uint16_t opcode);
    ...
    // YCPUDisassembler points to one of these functions (many more than these 2, just examples)
    std::string disassemble_ALU(std::string name, uint16_t operand, uint16_t nextword, uint16_t address,
                             bool show_memory_contents, uint16_t &instruction_size);
    std::string disassemble_BRA(std::string name, uint16_t operand, uint16_t nextword, uint16_t address,
                             bool show_memory_contents, uint16_t &instruction_size);
    ...
private:
    std::array<YCPUInstruction, 256> opcodes;
};

在设置过程中,我像这样初始化操作码:

void YCPU::initialize_opcodes()
{
    opcodes[0x01].initialize("CMP", &YCPU::CMP, &YCPU::disassemble_ALU, 0);
    opcodes[0x02].initialize("CMP", &YCPU::CMP, &YCPU::disassemble_ALU, 0);
    opcodes[0x03].initialize("CMP", &YCPU::CMP, &YCPU::disassemble_ALU, 0);
    ... // and so on for all instructions 
}

初始化后,我尝试这样调用成员函数:

void YCPU::run_one_instruction()
{
    ...
    uint16_t word = read_mem_int16(PC, SI_CS); // 0x1-0xff
    YCPUInstruction op = opcodes[word & 0xFFFF];
    (op.*YCPUInstruction::opcode)(word);
    ...
}

但是,这会引发我上面提到的编译器错误。

如果我首先取消引用 op,就像这样:

(op->*YCPUInstruction::opcode)(word);

我收到这个错误:

error: no match for 'operator->*' (operand types are 'YCPUInstruction' and 'YCPUOpcode' {aka 'void (YCPU::*)(short unsigned int)'})

如果我将语法更改为:

(op->*opcode)(word);

或:

(op.*opcode)(word)

我收到这个错误

error: 'opcode' was not declared in this scope

调用这些成员函数指针需要使用什么具体语法?

.*的左操作数必须引用/->*的左操作数必须指向包含class的成员函数的对象。右操作数可以是给出指向成员值的指针的任何表达式。

您正在使用的成员函数中包含 class 的是 YCPU,因此将 YCPUInstruction 作为左操作数是不正确的。我看到你的表达式在 YCPU 的另一个成员函数中,所以假设你想使用 *this 作为调用函数的 YCPU,你想要 this->*。下面的表达式可以是普通的 .-> 表达式,只是获取而不是调用 YCPUInstruction 中指向成员函数值的指针。由于 .*->* 的优先级很奇怪,因此通常需要并始终建议使用过多的括号。

void YCPU::run_one_instruction()
{
    // ...
    uint16_t word = read_mem_int16(PC, SI_CS); // 0x1-0xff
    YCPUInstruction op = opcodes[word & 0xFFFF];
    (this->*(op.opcode))(word);
    // ...
}