(我看到之前有人在 SO 上提出过类似的问题,但我看到的问题似乎并没有完全触及我的用例。特别是,我想知道我的编译失败是错误的结果,或者是我尝试的结果是 verboten。)
我希望实现委托(delegate)模式,用于事件处理。我认为也许满足我需求的最佳方法是成员函数指针映射,由 std::string 索引(代表事件类型。)
我开始尝试使用 std::function 来完成此操作,但遇到了一些问题,然后决定仅使用原始 MFP 进行尝试。 (我仍然愿意考虑 std::function,我会接受一个答案,该答案显示了如何使用该方法在下面完成我的确切需求。但我仍然想知道有什么问题我目前的方法。)
我能够通过一个类来完成这项工作。但是我实际上希望委托(delegate)映射由抽象基类提供,然后让派生类将其委托(delegate)注册到该映射中。除非我在下面的代码中犯了一些错误,否则这似乎是不可能的;看来成员函数指针不能是多态的。
我得到的编译错误是这样的:
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,我会这样说:
class Base
{
public:
struct EventContext
{
int data1;
};
Base() {}
virtual int ProcessEvent(std::string event, EventContext ctx) =0;
protected:
typedef std::function<int(const EventContext&)> HandlerType;
typedef std::map<std::string, HandlerType> EventDelegateMap;
EventDelegateMap _delegates;
};
class Derived: Base
{
public:
Derived();
int ProcessEvent(std::string event, EventContext ctx){ return 0; }
private:
int FooEventHandler(const EventContext& context){ return 0; }
int BarEventHandler(const EventContext& context){ return 0; }
int QuxEventHandler(const EventContext& context){ return 0; }
};
Derived::Derived() :Base()
{
auto self = this; // Some gcc versions cannot capture this correctly.
_delegates["foo"] = [=](const EventContext& context) { return self->FooEventHandler(context); };
_delegates["bar"] = [=](const EventContext& context) { return self->BarEventHandler(context); };
_delegates["qux"] = [=](const EventContext& context) { return self->QuxEventHandler(context); };
}
应该工作...
编辑:正如@Joachim 在他的评论中提到的,您也可以使用 std::bind() 生成所需的 std::function 对象,例如
_delegates["foo"] = std::bind(&Derived::FooEventHandler, this, std::placeholders::_1);
我使用 lambda 来表明在现实中,您可以在 lambda 中实现整个逻辑。这种方法的主要优点是,如果您要实现更多的处理程序,则工作量会更少,而且我总是赞成更少的工作量……:)
关于c++ - 具有派生成员函数指针的多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20186661/
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时