简体   繁体   English

C ++函数指针/回调的最佳实践

[英]Best Practice for C++ Function Pointers/Callbacks

I'm looking for some guidance in terms of best practices when dealing with custom callbacks or function pointers. 在处理自定义回调或函数指针时,我正在寻找最佳实践方面的一些指导。

I have two main use cases right now. 我现在有两个主要用例。

  1. I have a blocking loop inside my class that loops forever. 我的班级里面有一个阻塞循环,永远循环。 I want an external user to be able to specify a function that gets called on each iteration of that loop. 我希望外部用户能够指定在该循环的每次迭代中调用的函数。

Ex. 防爆。

myClass.setLoopFunction(doStuff); 

Where doStuff is a function located elsewhere that will get called on each iteration of the loop. doStuff是位于其他地方的函数,它将在循环的每次迭代中被调用。

  1. I get back an int from a function that can correspond to multiple values. 我从一个可以对应多个值的函数中获取一个int。 I want to dynamically map functions to those values so I can just do a lookup on the int I get back and then call the corresponding function. 我想动态地将函数映射到这些值,所以我可以在int上查找,然后调用相应的函数。

Ex. 防爆。

myFunctionMap[passedInt]();

Where the int acts as a key to lookup the correct function to call. 其中int充当查找正确函数的键。

I know my syntax here is probably off and I will need to use a std::map and be passing pointers etc, but any help, guidance or pitfalls would be appreciated. 我知道我的语法可能已关闭,我将需要使用std :: map并传递指针等,但任何帮助,指导或陷阱都将不胜感激。

Thanks! 谢谢!

EDIT: 编辑:

I have the following declared for now as a public variable: 我现在将以下声明为公共变量:

class Window {

public:
//The processing function can be from any class and takes in no arguments and returns void
template<class T>
std::function<void(T*, void)> processingFunction;

};

The functionality I want to have is that any class can pass in a function that takes in 0 arguments and returns void and I will set that as my processing function. 我想要的功能是任何类都可以传入一个接受0参数并返回void的函数,我会将其设置为我的处理函数。 In the while loop, I will execute that processingFunction and it will call the member function on that original class. 在while循环中,我将执行该processingFunction,它将调用该原始类的成员函数。

while(true) {
    if (exitCondition == false) {
        //Execute processing function
        processingFunction();
    }
    else {
        break;
    }
}

I feel like I'm completely missing something with templates, std::function and/or std::bind. 我觉得我完全错过了模板,std :: function和/或std :: bind的东西。 Then again it's been a good four hours of scouring the internet so maybe I just need to sleep on it. 然后,这是一个很好的四个小时的互联网搜索,所以也许我只需要睡在它上面。

I would recommend you use std::function< void() > instead of pointers. 我建议你使用std::function< void() >而不是指针。 Note that this is a TR1 addition to the standard library, you can use Boost implementation of it to work on older implementations. 请注意,这是标准库的TR1添加,您可以使用它的Boost实现来处理旧的实现。 The benefit of it is that it takes any kind of function that takes no arguments and returns something compatible with void (that is: returns anything). 它的好处是它采用任何类型的函数不带参数并返回与void兼容的东西(即:返回任何东西)。 You can use it in conjuntion with std::bind to get even more flexibility. 您可以将它与std::bind以获得更大的灵活性。

That said, you would still need an std::map< int, std::function< void() > > (or an ordinary std::vector if your indices are sequential) to map from indices to functions. 也就是说,你仍然需要一个std::map< int, std::function< void() > > (或者如果你的索引是顺序的普通的std::vector )来从索引映射到函数。

I suggest you define the callback to include a void * parameter, which the caller specifies when they install the callback. 我建议您定义回调以包含void *参数,调用者在安装回调时指定该参数。 This allows the caller to pass arbitrary data into their callback, which is often needed to provide context to that function. 这允许调用者将任意数据传递到它们的回调中,这通常需要为该函数提供上下文。 Callers not needing this parameter can use NULL to provide it. 不需要此参数的调用者可以使用NULL来提供它。

  1. If your callback eventually calls back into GUI-accessing code, you might need to dispatch control to the GUI thread ( Control.Invoke() and Control.BeginInvoke do this in .NET's WinForms ). 如果你的回调最终回调到GUI访问代码,你可能需要将控制权分派给GUI线程( Control.Invoke()Control.BeginInvoke在.NET的WinForms中执行此操作)。 That might cause deadlocks, so watch out. 这可能会导致死锁,所以要小心。
  2. As a generalization of the previous point, remember that during a callback call, your loop function won't be able to handle requests. 作为前一点的概括,请记住在回调调用期间,循环函数将无法处理请求。 So in the callback function, do as little work as possible, or spawn another thread if you need to do cpu-intensive stuff. 所以在回调函数中,尽可能少地工作,或者如果你需要做cpu密集的东西,则产生另一个线程。 And try to avoid calling blocking functions as well. 并尽量避免调用阻塞函数。
  3. Don't forget to unregister the callback ( myClass.setLoopFunction(NULL) ) once you no longer need it, and checking if it's set before you call it from the loop. 不再忘记在不再需要时取消注册回调( myClass.setLoopFunction(NULL) ),并在从循环中调用它之前检查它是否已设置。 This is optional, I just do it in order to provide a smoother cleanup. 这是可选的,我只是为了提供更顺畅的清理。 You might skip this if your loop needs high performance. 如果循环需要高性能,则可以跳过此步骤。
  4. What @K-ballo said. 什么@ K-ballo说。 About @mah's suggestion, it could be done using an interface or templates instead 关于@ mah的建议,可以使用界面或模板来完成

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM