我的C ++生疏了。我喜欢MyClass对Foo一无所知,并且有一个回调来在foo中运行一个函数。我不知道如何定义callback_pair或如何调用SetCallback
class MyClass{
tuple<cb, ptr> callback_pair
int run() {
auto that=callback_pair<1>();
auto cb = callback_pair<0>();
int a=1, b=2, c=3;
auto result = cb(that, a, b, c); //this calls foo.the_function
return result;
}
void SetCallback(tuple<cb, ptr> cb) { callback_pair=cb; )
};
class Foo {
int d;
int the_func(int a, b, c) {
return a+b+c+d
}
}
//myclass.SetCallback(what_do_I_write_here)
答案 0 :(得分:1)
好吧,MyClass
必须知道关于Foo
的某事,即您计划用作回调的任何方法的签名;否则,它将如何知道作为参数传递什么,或者期望获得什么类型作为输出?如果已知并修复了回调签名,例如上面的int(int,int,int)
,则可以使用如下结构:
class MyClass {
std::function<int(int,int,int)> callback;
public:
int run() {
return callback(1,2,3); // or whatever
}
template <typename Class>
void SetCallback (Class& o, int (Class::*m) (int,int,int)) {
callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); };
}
template <typename Class>
void SetCallback (Class const& o, int (Class::*m) (int,int,int) const) {
callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); };
}
};
MyClass
的上述实现的工作原理如下:callback
是一个函数对象,最初未定义,需要三个int
并返回int
。 SetCallback
有两个参数:应在其上执行回调的对象o
和该对象上符合m
签名的方法callback
。它并不关心o
的类型是什么;感谢类型擦除,MyClass
永远不需要知道它实际调用的是什么。
特别注意SetCallback
的两个版本 - const
和非const
对象各一个。实际上,您应该为volatile
和const volatile
编写重载,但这些重载比const
要少得多。将来,一旦异常规范和事务成为类型系统的一部分,我们也必须关心noexcept
和同步,如果没有一些非常聪明的语言,那么类型的组合爆炸将难以有效地处理支持。但是这个例子向您展示了如何编写这种代码,并且它可能足以满足您的需要。
实现看起来很难看,但它实际上提供了一个非常干净的界面;如上所述给定Foo
,您将使用MyClass
的回调功能,如下所示:
MyClass test;
Foo foo;
foo.d = 4;
test.SetCallback (foo, &Foo::the_func);
int result = test.run(); // result = 10
上述代码适用于任何具有签名int(int,int,int)
的方法的类型。请注意,在致电SetCallback
之前,您必须致电run
,否则您将获得std::bad_function_call
例外,因为尚未定义回调。