回调一个未知的类+函数

时间:2016-05-02 01:53:11

标签: c++

我的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)

1 个答案:

答案 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并返回intSetCallback有两个参数:应在其上执行回调的对象o和该对象上符合m签名的方法callback。它并不关心o的类型是什么;感谢类型擦除,MyClass永远不需要知道它实际调用的是什么。

特别注意SetCallback的两个版本 - const和非const对象各一个。实际上,您应该为volatileconst 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例外,因为尚未定义回调。