【发布时间】:2019-03-22 20:02:47
【问题描述】:
我正在编写一个 Gameboy 模拟器,对于 CPU 的指令,我在此处(在 cpp.hpp 中)使用此结构来存储有关它们的信息。该地图用于通过与其个人操作码相同的密钥访问所有这些信息:
struct instruction {
std::string name; //name of the instruction
int cycles; //clock cycles required to be executed
int paramNum; //number of params accepted
void* function; //code to be executed
};
class Cpu {
private:
std::map<unsigned char, instruction> instrMap;
void Cpu::fillInstructions(void);
instruction addInstruction(std::string, int, int, void*);
public:
void add_A_n(unsigned char);
}
然后在 cpu.cpp 中,我有一个函数,例如我想转换为函数指针以便分配给 struct 指令的字段。所以我有这个代码:
void Cpu::add_A_n(unsigned char n) {
//body
}
void Cpu::addInstructions(std::string name, int cycles, int paramNum, void* function) {
instruction i = {name, cycles, paramNum, function};
return i;
}
void Cpu::fillInstructions() {
instrMap[0x80] = Cpu::addInstruction("ADD A, n", 4, 0, (void*)&Cpu::add_A_n);
}
目标是从内存中获取操作码,然后使用此操作码从映射中检索有关相关指令的信息,最后通过使用 switch case 选择正确的指令来执行其功能:
((void (*)(void))instrMap[0x80].function)(); //for 0 params
((void (*)(unsigned char))instrMap[0x90].function)((unsigned char)operand); //for 1 param
我的目标是将所有函数,甚至是需要一些参数的函数,转换为结构中的函数。
正确执行了相应的功能,但引发了警告:
警告:从 'void (Cpu::)()' 转换为 'void' [-Wpmf-conversions] instrMap[0x80] = Cpu::addInstruction("ADD A, n", 4, 0, (void*)&Cpu::add_A_n);
我该如何解决?为什么会这样?谢谢
【问题讨论】:
-
我认为这不是实现 CPU 仿真器的最佳方式,因为通过将函数指针传递为
void*会失去类型安全性。您是否考虑过使用结构将传递给virtual函数的参数存储在代表指令的子类中? -
不请自来的建议:使用
std::unordered_map,除非您需要在地图中订购,而您可能不需要。 (标准中还有一个平面地图待定,Google 的flat_hash_map 暂时。) -
@metal 它确实需要 C++11,但我可能需要使用它。
-
您还可以从派生 std 版本的
boost::unordered_map获取与 C++98 兼容的哈希映射。