C ++:带状态的回调函数

时间:2016-06-28 09:36:55

标签: c++ callback

我使用以C(library_function)编写的外部库函数,该函数将回调函数作为参数。库调用回调函数的参数对我来说并不重要。我唯一感兴趣的是调用回调函数的顺序。我希望回调函数在每次调用时返回列表的下一个元素。

考虑这个例子:

#include <iostream>

int x;
bool *booleans;

void library_function(bool(*callback_fn)()){
    for (int i=0; i < 5; i++) {
        std::cout << callback_fn() << std::endl;
    }
}

bool my_callback_fn(){
    return booleans[x++];
}

void my_function(bool b[]){
    x = 0;
    booleans = b;

    library_function(my_callback_fn);
}

int main() {
    bool booleans[] {true, false, true, true, false};
    my_function(booleans);
}

这段代码有效,但我不得不使用全局变量,我觉得这种变量并不好。

在Python中,我会使用内部函数来实现这个目的:

def library_function(callback_fn):
    for _ in range(5):
        print(callback_fn())


def my_function(b):
    x = -1

    def my_callback_fn():
        nonlocal x
        x += 1
        return b[x]

    library_function(my_callback_fn)

if __name__ == '__main__':
    booleans = [True, False, True, True, False]
    my_function(booleans)

我已经读过C ++不支持nested functions,并且如果lambda函数不是capture variables,那么它们只能用作函数指针。

有没有办法避免使用全局变量,但仍然能够修改内部状态&#39;回调函数?

3 个答案:

答案 0 :(得分:1)

  

我正在使用C(library_function)编写的外部库函数,该函数将回调函数作为参数。

除非外部库允许您传递用户定义的上下文,例如提供回调签名,如

bool(*callback_fn)(void*)
                // ^^^^^
  

有没有办法避免使用全局变量但仍能修改回调函数的“内部状态”?

除了使用全局上下文之外别无选择。

答案 1 :(得分:0)

嗯......它可以帮到你

void fn()
{
//tip: you can't use a struct in function to be a template argument.
    struct _function
    {
     static void foo()
        {
        }
    };
}

如果你有一个c ++ 11支持编译器,你可以这样做

void(*)(int) fn()
{
    return [&](int){code block};// for cast it to a function pointer you can not capture any variable in code block.
}

答案 2 :(得分:0)

感谢πάντα ῥεῖ的评论,我写了一个包含我的回调函数状态的类:

#include <iostream>

void library_function(bool(*callback_fn)()){
    for (int i=0; i < 5; i++) {
        std::cout << callback_fn() << std::endl;
    }
}

class CallbackClass
{
    static bool *booleans;
    static int i;

    static bool my_callback_fn(){
        return booleans[i++];
    }

public:
    static void my_function(bool b[]){
        i = 0;
        booleans = b;
        library_function(my_callback_fn);
    }
};

int CallbackClass::i {};
bool* CallbackClass::booleans {nullptr};


int main() {
    bool booleans[] {true, false, true, true, false};
    CallbackClass::my_function(booleans);
}

这适合我。