带有函数指针的c++事件处理接口

C++ event handling interface with function pointers

本文关键字:c++ 事件处理 接口 指针 函数      更新时间:2023-10-16

我想在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 Dateieneventhandler.cpp" -o "U:Eigene Dateieneventhandler.exe"    -I"C:Dev-Cpplibgccmingw323.4.2include"  -I"C:Dev-Cppincludec++3.4.2backward"  -I"C:Dev-Cppincludec++3.4.2mingw32"  -I"C:Dev-Cppincludec++3.4.2"  -I"C:Dev-Cppinclude"   -L"C:Dev-Cpplib" 
U:Eigene Dateieneventhandler.cpp: In constructor `Pong_Game::Pong_Game()':
U:Eigene Dateieneventhandler.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 Dateieneventhandler.cpp:45: error: cannot convert `void (Pong_Game::*)(int)' to `void (*)(int)' in assignment
U:Eigene Dateieneventhandler.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 Dateieneventhandler.cpp:46: error: cannot convert `void (Pong_Game::*)(int)' to `void (*)(int)' in assignment
Execution terminated

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

谢谢!

  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的球拍在这里……"(尽管可能还有其他方法可以解决这个问题)。