#c #c 11
#c #c 11 #c
Вопрос:
Я кодирую эмулятор Gameboy, и для инструкций процессора я использую эту структуру здесь (в 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*)amp;Cpu::add_A_n);
}
Цель состоит в том, чтобы извлечь код операции из памяти, затем использовать этот код операции для извлечения из карты информации об относительной инструкции и, наконец, выполнить ее функцию, используя регистр переключения для выбора правильной:
((void (*)(void))instrMap[0x80].function)(); //for 0 params
((void (*)(unsigned char))instrMap[0x90].function)((unsigned char)operand); //for 1 param
Моя цель — привести все функции, даже те, которым требуются некоторые параметры, к той, что находится в структуре.
Соответствующая функция выполняется корректно, но выдается предупреждение:
предупреждение: преобразование из ‘void (Cpu::)()’ в ‘void‘ [-Wpmf-conversations] instrMap[0x80] = Cpu::addInstruction(«ДОБАВИТЬ A, n», 4, 0, (void*)amp;Cpu::add_A_n);
Как я могу это решить и почему это происходит? Спасибо
Комментарии:
1. Я не думаю, что это лучший способ реализовать эмулятор процессора, потому что вы теряете безопасность типов, передавая указатели на функции как
void*
. Думали ли вы об использовании структуры для хранения параметров, переданныхvirtual
функции в подклассе, который вместо этого представляет инструкцию?2. Непрошеный совет: используйте
std::unordered_map
, если вам не нужен порядок в вашей карте, чего вы, вероятно, не делаете. (В настоящее время также ожидается создание плоской карты в стандарте и в flat_hash_map от Google.)3. @metal Для этого требуется C 11, но мне, вероятно, потребуется его использовать.
4. Вы также можете получить совместимую с C 98 хэш-карту из
boost::unordered_map
, из которой была получена версия std.
Ответ №1:
amp;Cpu::add_A_n
возвращает указатель на функцию-член, который сильно отличается от обычного указателя на функцию, и их нельзя смешивать. Странность, связанная с указателем на функции-члены, заключается в том, что всем нестатическим функциям-членам требуется this
экземпляр для вызова функции.
В вашем случае, если функция, подобная add_A_n
действительно не зависит от this
, просто создайте ее static
или функцию, не являющуюся членом:
class Cpu {
...
static add_A_n(unsigned char);
};
Таким образом, больше не требуется this
вызывать a, и amp;Cpu::add_A_n
он становится обычным указателем на функцию.