如何在C++; 原谅我问这个基本问题的无知,但我已经习惯了使用Python,在这种情况下,我完全忘记了我将如何在C++中尝试这个问题。
我希望能够将回调传递给在后台执行缓慢进程的函数,并在进程完成后调用它。此回调可以是自由函数、静态函数或成员函数。我还希望能够为上下文插入一些任意的参数。(即,在某种程度上实现一个非常糟糕的人的协同程序。)除此之外,这个函数将始终采用std::string,这是进程的输出。我不介意这个参数在最终回调参数列表中的位置是否是固定的如何在C++; 原谅我问这个基本问题的无知,但我已经习惯了使用Python,在这种情况下,我完全忘记了我将如何在C++中尝试这个问题。,c++,boost,boost-bind,C++,Boost,Boost Bind,我希望能够将回调传递给在后台执行缓慢进程的函数,并在进程完成后调用它。此回调可以是自由函数、静态函数或成员函数。我还希望能够为上下文插入一些任意的参数。(即,在某种程度上实现一个非常糟糕的人的协同程序。)除此之外,这个函数将始终采用std::string,这是进程的输出。我不介意这个参数在最终回调参数列表中的位置是否是固定的 我觉得答案将涉及boost::bind和boost::function,但我无法计算出创建任意可调用项(同时将它们转换为仅获取单个字符串)、将它们存储在后台进程中所需的精确
我觉得答案将涉及boost::bind和boost::function,但我无法计算出创建任意可调用项(同时将它们转换为仅获取单个字符串)、将它们存储在后台进程中所需的精确调用,并使用string参数正确调用callable。听起来像是要使用。回调应存储为
boost::function
。然后,您可以通过绑定其他参数,使用boost::bind
将任何其他函数签名“转换”为此类对象
例子
我没有试图编译这个,但它应该显示出总体思路
void DoLongOperation(boost::function<void, const std::string&> callback)
{
std::string result = DoSomeLengthyStuff();
callback(result);
}
void CompleteRoutine1(const std::string&);
void CompleteRoutine2(int param, const std::string&);
// Calling examples
DoLongOperation(&CompleteRoutine1); // Matches directly
DoLongOperation(boost::bind(&CompleteRoutine2, 7, _1)); // int parameter is bound to constant.
// This one is thanks to David Rodríguez comment below, but reformatted here:
struct S
{
void f( std::string const & );
};
int main()
{
S s;
DoLongOperation( boost::bind( &S::f, &s, _1 ) );
}
void-dolong操作(boost::函数回调)
{
std::string result=DoSomeLengthyStuff();
回调(结果);
}
void CompleteRoutine1(const std::string&);
void CompleteRoutine2(int参数,const std::string&);
//举例
dolong操作(&CompleteRoutine1);//直接匹配
dolong操作(boost::bind(&CompleteRoutine2,7,_1));//int参数绑定到常量。
//这一条要感谢大卫·罗德里格斯(David Rodríguez)在下面的评论,但在这里重新格式化:
结构
{
void f(std::string const&);
};
int main()
{
S S;
dolong操作(boost::bind(&S::f,&S,_1));
}
最简单的方法:
class Callback
{
public:
virtual ~Callback() {}
virtual Callback* clone() const = 0;
// Better to wrap the call (logging, try/catch, etc)
void execute(const std::string& result) { this->executeImpl(result); }
protected:
// Don't make sense to have them public
Callback() {}
Callback(const Callback&) {}
Callback& operator=(const Callback&) { return *this; }
private:
virtual void executeImpl(const std::string& result) = 0;
};
// Example
class Example: public Callback
{
public:
Example(int a, int b): Callback(), mA(a), mB(b) {}
virtual Example* clone() const { return new Example(*this); }
private:
virtual void executeImpl(const std::string& result) {}
int mA;
int mB;
};
然后,您可以(通过指针/引用)将回调类传递给进程。该类具有所需的状态,必要时可以复制(如果没有,请删除克隆)。Don;传递一个回调函数,传递一个对象。我真的不明白你为什么认为你必须给它注入动力。对象,schmobject。回调摇滚!;)@尼尔:啊,我明白你的意思了。我的意思是,在链的末端,会有某种类型的适当功能。(因为这最终是你完成事情的方式。)但我没想到会在这里直接通过;我希望能通过引用其中的一个函子,这篇白皮书提供了许多方法来编写C++中合理的通用回调,虽然读起来很简洁,但它可能会对你的利益有好处;啊,我希望我知道在这种情况下“利用绑定或类型擦除”是什么意思。:)我不能对需要通知的对象强加接口要求。他们唯一的要求就是拥有一个正确签名的函数。事实上,我将要调用的东西甚至不能保证是一个对象。它可能是一个免费函数。你能举个例子吗?(或指向特定示例的链接)我已经有了一个好主意,boost::function和boost::bind可以实现我想要的功能,但我不知道如何实现它。+1对于成员函数示例:
struct S{void f(std::string const&);};int main(){S;DoLongOperation(boost::bind(&S::f,&S,_1));}
如果你想添加额外的参数,请记住,boost::bind
将复制这些参数。不幸的是,这似乎需要从回调中为我拥有的每个调用站点派生一个新类,这是我绝对希望避免的。是和否,每个功能只需要一个类,这对我来说并不不合理。毕竟,每个功能不都有一个函数吗?回调的典型用法是一行程序调用例程,并在最后传递希望它调用的函数。在更复杂的情况下,从成员函数转换为自由函数或添加额外参数可能需要2或3行(例如boost::bind)。这是10行或11行,相比之下太笨拙了。是的,对于一行来说,它可能有点笨拙:)我以为您已经考虑了完全成熟的回调,在这种情况下,再多几行并不重要,因为它们与函数体本身相比,数量级少了一个数量级。