I'm trying to dereference a method pointer stored in a static array and call it from within a method, but I'm getting the following error:
error: 'chip8::Chip8::table[0]' cannot be used as a member pointer, since it is of type 'void (*)()'
(this->*table[0])();
^
Here is my class declaration (chip.hpp):
class Chip8{
private:
static void (*table[16])(); //function pointer table
//...
public:
void cycle();
//...
};
and here are the implementations of Chip8::cycle and Chip8::table (chip.cpp):
void (Chip8::*table[16])() = {
&Chip8::opcode0,
&Chip8::JP_1nnn,
&Chip8::CALL_2nnn,
&Chip8::SE_3xkk,
&Chip8::SNE_4xkk,
&Chip8::SE_5xy0,
&Chip8::LD_6xkk,
&Chip8::ADD_7xkk,
&Chip8::opcode8,
&Chip8::SNE_9xy0,
&Chip8::LD_Annn,
&Chip8::JP_Bnnn,
&Chip8::RND_Cxkk,
&Chip8::DRW_Dxyn,
&Chip8::opcodeE,
&Chip8::opcodeF
};
void Chip8::cycle(){
opcode = (memory[pc] << 8) | memory[pc+1];
pc+=2;
(this->*table[0])(); // error here
if(dt > 0){
dt--;
}
if(st > 0){
st--;
}
}
EDIT: Here are the declarations of the functions assigned to the table:
//Function table extensions
void opcode0();
void opcode8();
void opcodeE();
void opcodeF();
//Instructions
void CLS_00E0(); // Clears screen
void RET_00EE(); // Pops new pc off the stack
void JP_1nnn(); // Jumps to nnn
void CALL_2nnn(); // Pushes current pc to stack and jumps to nnn
void SE_3xkk(); // Skip next instruction if Vx = kk
void SNE_4xkk(); // Skip next instruction if Vx != kk
void SE_5xy0(); // Skip next instruction if Vx == Vy
void LD_6xkk(); // Set Vx = kk
void ADD_7xkk(); // Vx += kk
void LD_8xy0(); // Vx = Vy
void OR_8xy1(); // Vx |= Vy
void AND_8xy2(); // Vx &= Vy
void XOR_8xy3(); // Vx ^= Vy
void ADD_8xy4(); // Vx += Vy, if the sum is greater than 255, then VF = 1
void SUB_8xy5(); // Vx -= Vy, if Vx > Vy, then VF = 1, otherwise VF = 0
void SHR_8xy6(); // Vx >>= 1, if least significant bit of Vx is 1, then VF is set to 1, otherwise 0
void SUBN_8xy7(); // Vx = Vy - Vx, if Vy > Vx, VF = 1, otherwise VF = 0
void SHL_8xyE(); // Vx <<= 1, if most significant bit of Vx is 1, then VF is set to 1, otherwise 0
void SNE_9xy0(); // Skip next instruction if Vx != Vy
void LD_Annn(); // I = nnn
void JP_Bnnn(); // Jumps to nnn + V0
void RND_Cxkk(); // Vx = random byte & kk
void DRW_Dxyn(); // Draws n-byte (n = height) sprite starting at Vx and Vy. If collision detected, VF = 1
void SKP_Ex9E(); // Skip next instruction if value of Vx is pressed
void SKNP_ExA1(); // Skip next instruction if value of Vx isn't pressed
void LD_Fx07(); // Set Vx = delay timer
void LD_Fx0A(); // Wait for key press and store value in Vx
void LD_Fx15(); // Set delay timer = Vx
void LD_Fx18(); // Set sound timer = Vx
void ADD_Fx1E(); // Set I += Vx
void LD_Fx29(); // Set I = memory location of digit sprite in Vx
void LD_Fx33(); // Store BCD representation of value of Vx in I, I+1, I+2
void LD_Fx55(); // Store registers V0 through Vx (including) starting at memory location I
void LD_Fx65(); // Read registers V0 through Vx (including) starting at memory location I
What is the problem and how can I fix it?
The problem is that when you wrote:
static void (*table[16])();
you're declaring a static data member named table
that is an array of size 16
whose elements are pointers to free function with no parameter and return type of int.
But what you actually want is a table
that is an array of size 16
whose elements are pointers to the member functions of Chip8
which you can do as shown below:
class Chip8{
private:
//---------------vvvvvvvv------------>note the added Chip8::* indicating that a pointer to a member function instead of free function
static void (Chip8::*table[16])(); //function pointer table
public:
void cycle();
void opcode0();
};
//definition for the static data member `table`
void (Chip8::*Chip8::table[16])() = {
&Chip8::opcode0,
};
void Chip8::opcode0()
{
std::cout<<"opcode0 called"<<std::endl;
}
void Chip8::cycle(){
std::cout<<"cycle called"<<std::endl;
(this->*table[0])();
}
int main()
{
Chip8 chip;
chip.cycle();
return 0;
}
Note that you can make the above code more readable using alias declaration as shown below:
class Chip8{
private:
using type = void (Chip8::*)();
static type table[16]; //function pointer table
public:
void cycle();
void opcode0();
};
Chip8::type Chip8::table[16] = {
&Chip8::opcode0,
};
void Chip8::opcode0()
{
std::cout<<"opcode0 called"<<std::endl;
}
void Chip8::cycle(){
std::cout<<"cycle called"<<std::endl;
(this->*table[0])();
}
int main()
{
Chip8 chip;
chip.cycle();
return 0;
}