将功能指针存储到任何成员函数

dan*_*jar 3 c++ events function-pointers function

我的活动经理

对于事件管理器,我需要在向量中存储许多指向函数的指针,以便在触发事件时调用它们.(我将在本问题的最后提供EventFunction助手类的源代码.)

// an event is defined by a string name and a number
typedef pair<string, int> EventKey;

// EventFunction holds a pointer to a listener function with or without data parameter
typedef unordered_map<EventKey, vector<EventFunction>> ListEvent;

// stores all events and their listeners
ListEvent List;
Run Code Online (Sandbox Code Playgroud)

注册侦听器可以通过调用第一个或第二个函数来完成,具体取决于您是否希望接收其他数据.(此代码来自我的事件管理器类.)

public:
  typedef void (*EventFunctionPointer)();
  typedef void (*EventFunctionPointerData)(void* Data);

  // let components register for events by functions with or without data parameter,
  // internally simple create a EventFunction object and call the private function
  void ManagerEvent::Listen(EventFunctionPointer Function, string Name, int State);
  void ManagerEvent::Listen(EventFunctionPointerData Function, string Name, int State);

private:
  void ManagerEvent::Listen(EventFunction Function, string Name, int State)
  {
    EventKey Key(Name, State);
    List[Key].push_back(Function);
  }  
Run Code Online (Sandbox Code Playgroud)

会员功能指针

该代码不起作用,因为我存储函数指针但不存储我的List中的成员函数指针.所有这些指针都应该是成员函数指针,因为类似的组件ComponentSound"PlayerLevelup"在其成员函数的基础上监听事件,以便在ComponentSound::PlayerLevelup触发事件时发出良好的声音.

C++中的成员函数指针如下所示.

// ReturnType (Class::*MemberFunction)(Parameters);
void (ComponentSound::*PlayerLevelup)();
Run Code Online (Sandbox Code Playgroud)

问题是,任何组件类都应该能够侦听事件,但是在事件管理器中存储成员函数指针需要我指定监听类.正如您在示例中所看到的,我需要指定ComponentSound但事件管理器应该只有一个成员函数指向任何类的向量.

回答其中一个问题对我有很大帮助.

  • 如何在事件管理器中的向量中存储函数指针到任何成员函数?(也许它有助于所有的侦听功能都从一个抽象类继承Component.)
  • 如何以另一种方式设计我的事件管理器以实现目标功能?(我想使用字符串和int键来表示消息.)

我试图保持我的问题一般,但如果你需要更多的信息或代码,请评论.

分配

在我的成员函数指针向量中,我使用EventFunction而不是仅提供两种消息类型的指针.一个有,一个没有数据参数.

class EventFunction
{
private: EventFunctionPointer Pointer; EventFunctionPointerData PointerData; bool Data;
public:
    EventFunction(EventFunctionPointer Pointer) : Pointer(Pointer), PointerData(NULL), Data(false) { }
    EventFunction(EventFunctionPointerData PointerData) : PointerData(PointerData), Pointer(NULL), Data(true) { }
    EventFunctionPointer GetFunction() { return Pointer; }
    EventFunctionPointerData GetFunctionData() { return PointerData; } bool IsData() { return Data; }
    void Call(void* Data = NULL){ if(this->Data) PointerData(Data); else Pointer(); }
};
Run Code Online (Sandbox Code Playgroud)

roo*_*han 5

您可以使用函子来实现这一点。如果你在成员函数周围包裹一个函子,你可以用函子制作一个向量。一个函子看起来像这样:

template <class T> class MyFunctor
{
private:
    T* ObjectPtr;
    void (T::*MemberFunction) ();
public:
    void operator () ()
    {
        return (*this->ObjectPtr.*this->MemberFunction)();
    }
};
Run Code Online (Sandbox Code Playgroud)

所以基本上一个函子覆盖 () 运算符并返回存储在函子类中的成员函数。如果您希望函子使用不同的签名,则它们可能会非常复杂,但在本文中您可以获得更多信息。

http://www.codeproject.com/Articles/7112/Pointers-to-Member-Functions-and-Functors


Pup*_*ppy 5

你将不得不使用std::function.这是实现泛型回调的唯一方法.只要涉及函数指针而不是函数对象,它就不是通用的,永远不会是通用的,永远不能成为通用的.

unordered_map<string, vector<std::function<void()>>>
Run Code Online (Sandbox Code Playgroud)

函数指针很糟糕,不应该在C++中显式使用,只传递给像std::bindstd::function构造函数这样的模板,而成员函数指针则更糟糕.