Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C+的最佳实践+;函数指针/回调_C++ - Fatal编程技术网

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

C++ C+的最佳实践+;函数指针/回调,c++,C++,在处理自定义回调或函数指针时,我正在寻找一些最佳实践方面的指导 我现在有两个主要的用例 我的类中有一个永远循环的阻塞循环。我希望外部用户能够指定在该循环的每次迭代中调用的函数 前 其中doStuff是一个位于别处的函数,它将在循环的每次迭代中被调用 我从一个可以对应多个值的函数中返回一个int。我想动态地将函数映射到这些值,这样我就可以对返回的int进行查找,然后调用相应的函数 前 其中int作为键来查找要调用的正确函数 我知道我这里的语法可能不正确,我需要使用std::map并传递指针等,但任

在处理自定义回调或函数指针时,我正在寻找一些最佳实践方面的指导

我现在有两个主要的用例

  • 我的类中有一个永远循环的阻塞循环。我希望外部用户能够指定在该循环的每次迭代中调用的函数
  • 其中doStuff是一个位于别处的函数,它将在循环的每次迭代中被调用

  • 我从一个可以对应多个值的函数中返回一个int。我想动态地将函数映射到这些值,这样我就可以对返回的int进行查找,然后调用相应的函数
  • 其中int作为键来查找要调用的正确函数

    我知道我这里的语法可能不正确,我需要使用std::map并传递指针等,但任何帮助、指导或陷阱都将不胜感激

    谢谢

    编辑:

    目前,我已将以下内容声明为公共变量:

    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;
    
    };
    

    我觉得我完全缺少模板、std::function和/或std::bind。我又花了四个小时浏览互联网,也许我只需要睡一觉

    我建议您使用
    std::function
    而不是指针。请注意,这是对标准库的TR1添加,您可以使用它的Boost实现来处理旧的实现。它的好处是,它接受任何类型的函数,这些函数不带参数,并返回与
    void
    兼容的内容(即:返回任何内容)。您可以将它与
    std::bind
    结合使用,以获得更大的灵活性


    也就是说,您仍然需要一个
    std::map
    (或者如果索引是连续的,则需要一个普通的
    std::vector
    )来从索引映射到函数。

    我建议您将回调定义为包含一个
    void*
    参数,调用者在安装回调时指定该参数。这允许调用方将任意数据传递到其回调中,而回调通常是为该函数提供上下文所必需的。不需要此参数的调用方可以使用NULL来提供它

  • 如果回调最终调用GUI访问代码,则可能需要将控件分派到GUI线程(
    control.Invoke()
    control.BeginInvoke
    在.NET的WinForms中执行此操作)。这可能会导致死锁,所以要小心
  • 作为前一点的概括,请记住,在回调调用期间,循环函数将无法处理请求。因此,在回调函数中,尽可能少地执行一些工作,或者如果需要执行cpu密集型任务,则生成另一个线程。并尽量避免调用阻塞函数
  • 一旦不再需要回调(
    myClass.setLoopFunction(NULL)
    ),不要忘记注销它,并在从循环调用它之前检查它是否已设置。这是可选的,我这样做只是为了提供更平滑的清理。如果循环需要高性能,可以跳过此步骤
  • @K-ballo说了些什么。关于@mah的建议,可以使用接口或模板代替

  • 这真是太好了。。。在C++中有很多更好的方法!使用
    void*
    几乎总是一个糟糕的主意。酷,今晚我会试试。我是否应该担心性能方面的问题?对于无限while循环中的回调,比映射更重要。@Jon:是的,至少在Boost函数实现中,每个调用相当于两个常规函数调用或类似的调用。这一切都在他们避免虚拟调度的理由中得到了解释。这似乎比我想象的要困难。由于格式原因删除了注释,并编辑了我的原始问题。虽然这不是我需要的解决方案,但这并不是因为这个答案是错误的,而是因为我不了解如何正确使用std::function和bind。这仍然是一个复选标记,因为它引导我找到了使用上面的回调库的解决方案。所以我发现:它基本上完成了我需要它做的所有事情,而且似乎是一个性能良好的速率。为什么要重新发明方向盘?我仍然想进一步探索这段代码以真正理解它,但现在它解决了我的问题。谢谢大家的帮助/指导。
    myFunctionMap[passedInt]();
    
    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;
    
    };
    
    while(true) {
        if (exitCondition == false) {
            //Execute processing function
            processingFunction();
        }
        else {
            break;
        }
    }