-2

我想为 C++ 中的简单游戏实现一个带有函数指针的简单事件接口。这样做是为了改进 allegro lib 的事件接口。因此,我编写了以下代码,但它不起作用。

typedef void (*event_handler)(int); //type for the event handler
const int TESTKEY_A = 1; // example Key as event arg

class Game
{
      private:
              bool is_running ;
      protected:
               event_handler on_key_down[2];
      public:
               void run();
               void do_events(int e) ;
               void stop() {is_running = false;}
};
void Game::run()
{
    is_running=true; 
    while(is_running) 
        do_events(1);
}

void Game::do_events(int e) 
{
    if(e==1) 
    {
        for(int i = 0; i < 2 ;i++)
            on_key_down[i](TESTKEY_A);
    }
}

class Pong_Game : public Game
{
      public:
               Pong_Game();
               void On_Key_Down_Player1(int key) { return;}
               void On_Key_Down_Player2(int key) { return;}
};

Pong_Game::Pong_Game()
{
    on_key_down[0] = &this->On_Key_Down_Player1;
    on_key_down[1] = &this->On_Key_Down_Player2;
}

int main()
{
    Game *my_game = new Pong_Game();
    my_game->run();
    return 0;
}

编译器日志:

Compiler: Default compiler
Executing  g++.exe...
g++.exe "U:\Eigene Dateien\eventhandler.cpp" -o "U:\Eigene Dateien\eventhandler.exe"    -I"C:\Dev-Cpp\lib\gcc\mingw32\3.4.2\include"  -I"C:\Dev-Cpp\include\c++\3.4.2\backward"  -I"C:\Dev-Cpp\include\c++\3.4.2\mingw32"  -I"C:\Dev-Cpp\include\c++\3.4.2"  -I"C:\Dev-Cpp\include"   -L"C:\Dev-Cpp\lib" 
U:\Eigene Dateien\eventhandler.cpp: In constructor `Pong_Game::Pong_Game()':
U:\Eigene Dateien\eventhandler.cpp:45: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say `&Pong_Game::On_Key_Down_Player1'
U:\Eigene Dateien\eventhandler.cpp:45: error: cannot convert `void (Pong_Game::*)(int)' to `void (*)(int)' in assignment
U:\Eigene Dateien\eventhandler.cpp:46: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function.  Say `&Pong_Game::On_Key_Down_Player2'
U:\Eigene Dateien\eventhandler.cpp:46: error: cannot convert `void (Pong_Game::*)(int)' to `void (*)(int)' in assignment

Execution terminated

编辑: - 更改代码 - 添加编译器日志

谢谢!

4

1 回答 1

1
  1. 您正在使用成员函数来初始化“普通”函数指针。成员函数与“普通”函数的不同之处在于它们具有T *this与函数一起传递的隐藏函数。
  2. 这似乎是通过继承实现的“事件处理程序”接口比使用函数指针更好地解决的问题。

像这样的东西:

class Game
{
    private:
        bool is_running ;
    public:
        void run(){is_running=true; while(is_running) do_events(1);}
        void do_events(int e) {if(e==1) On_Key_Down(TESTKEY_A);}
        void stop() {is_running = false;}

        virtual void On_Key_Down(int key) = 0;
        ... other event handlers here ... 
};

class Pong_Game : public Game
{
    public:
        void Pong_Game() {}
        void On_Key_Down(int key) { // handle key event...}
        ... other event handlers here ... 
};

根据评论:要覆盖多个玩家,您可能需要实现“每个玩家事件处理”:

class Player 
{
  public:
    enum moves { move_up, 
                 move_down, 
                 move_left, 
                 move_right, 
                 move_jump, 
                 move_shoot, ...  }; 

    ... 
    virtual void On_Key_Down(int key) = 0;
    ... 
};

class Player_A
{
   public:
    ...
    virtual moves On_Key_Down(int key) { if (key == 'W') return move_up;  ...  }
}

class Player_B
{
   public:
    ...
    virtual moves On_Key_Down(int key) { if (key == 'I') return move_up;  ...  }
}


class Pong_Game : public Game
{
    private:
        vector<Player *> players;
    public:

        void Pong_Game() {}
        void On_Key_Down(int key) 
        { 
           for(p : players) {
               Player::moves m =  p->On_key_down(); 
               ...  
            }
        }
        ... other event handlers here ... 
};

(这很快就被破解了——“动作”可能放在其他地方更好,确切的结构只是“我现在能想到的”——你可能需要一个class Player_A_Pong : public Player_A或一些这样的东西来处理“球员 A 的球拍在这里,球员 B 的球拍在这里......” - 尽管可能还有其他方法可以处理)。

于 2013-06-11T09:21:11.353 回答