【发布时间】:2013-12-09 19:12:59
【问题描述】:
(我看到以前曾在 SO 上提出过类似的问题,但我所看到的问题似乎并没有完全触及我的用例。特别是,我想知道我的编译失败是错误的结果,或者是我尝试禁止的结果。)
背景
我希望实现委托模式,用于事件处理。我认为可能满足我需求的最佳方法是成员函数指针的映射,由 std::string (代表事件类型)索引。
我开始尝试使用 std::function 来完成此任务,但遇到了一些问题,然后决定仅使用原始 MFP 进行尝试。 (我仍然愿意考虑std::function,并且我会接受一个答案,说明如何使用该方法在下面完成我的确切需求。但我仍然想知道我目前的方法有什么问题。)
我能够通过一个班级来完成这项工作。但是我实际上希望委托映射由抽象基类提供,然后让派生类将其委托注册到该映射中。除非我在下面的代码中犯了一些错误,否则这似乎是不可能的;看来成员函数指针不能是多态的。
我得到的编译错误如下所示:
mfp5.cpp: In constructor ‘Derived::Derived()’:
mfp5.cpp:41:21: error: cannot convert ‘int (Derived::*)(const Base::EventContext&)’ to ‘std::map<std::basic_string<char>, int (Base::*)(const Base::EventContext&)>::mapped_type {aka int (Base::*)(const Base::EventContext&)}’ in assignment
_delegates["foo"] = &Derived::FooEventHandler;
问题
- 是我在下面的代码中犯了一个错误,还是真的不允许这样做?简而言之,我有一个
Base::*的std::map,我想在其中插入一些Derived::*。 - 是否有其他推荐的方法来完成此操作?
代码
class Base
{
public:
struct EventContext
{
int data1;
};
Base() {}
virtual int ProcessEvent(std::string event, EventContext ctx) =0;
protected:
typedef int (Base::* EventHandler)(const EventContext& context);
typedef std::map<std::string, EventHandler> EventDelegateMap;
EventDelegateMap _delegates;
};
.
class Derived: Base
{
public:
Derived();
int ProcessEvent(std::string event, EventContext ctx);
private:
int FooEventHandler(const EventContext& context);
int BarEventHandler(const EventContext& context);
int QuxEventHandler(const EventContext& context);
};
Derived::Derived() :Base()
{
_delegates["foo"] = &Derived::FooEventHandler; // error
_delegates["bar"] = &Derived::BarEventHandler; // error
_delegates["qux"] = &Derived::QuxEventHandler; // error
}
【问题讨论】:
-
我很好奇您使用
std::function的解决方案是什么样的。使用std::function将使整个事情更加通用(如果需要,您可以使用 lambda 或非成员函数,或者提出一个不需要继承的系统)。 -
基本上,我尝试了这个(以及其他一些排列):
typedef int (Base::*EventHandler)(const EventContext& context); typedef std::function<EventHandler> EventDelegate; typedef std::map<std::string, EventDelegate> EventDelegateMap;但我被一些神秘的、无法形容的编译器错误所阻碍。 (编译器警告和错误的可理解性是 C++ 模板中最糟糕的部分。) -
另外,对于我这里的用例,我不需要灵活地使用 lambdas 等。
-
具有讽刺意味的是,我接受的答案提倡为此使用 lambda。 :)
标签: c++ inheritance polymorphism member-function-pointers