【发布时间】:2019-11-21 07:09:22
【问题描述】:
我有一些订阅函数,当有事情发生时会调用我的回调。 (假设它是一个计时器,当经过一定的毫秒数时会传递给我一个对象。)我想要调用的是一个虚拟方法。我觉得 std::function 和 std::bind 或 lambdas 是解决方案的一部分。
到目前为止,我使用的 C++99 方法涉及知道如何调用虚方法的单行 C 函数。订阅函数将 C 函数和一个 void* 用户数据作为参数。例如:
class Foo {
virtual void OnTimerA( Data* pd );
};
void OnTimerACB( Data* pd, void* pvUserData ) {
( (Foo*) pvUserData )->OnTimerA( pd );
}
/* Inside some method of Foo; 1000 is a number of milliseconds to call me back in;
second arg is a function pointer; third is a void* user data that is passed back
to the C callback. */
SubscribeToTimerOld( 1000, OnTimerACB, this );
我希望的是一种写作方式:
SubscribeToTimerNew( 1000, OnTimerA );
或类似的东西,至少不需要编写单行 C 绑定回调。
我感觉SubscribeToTimerNew() 的参数可能是某种std:function,而不仅仅是写OnTimerA,我必须用std::bind 写一些东西来获取this 指针在那里。
除了bind,也许 lambda 是一种方法?这可以编译,但我不知道如何扩展它以让事件处理程序将参数传递给OnTimerA()。 (我的链接器当前不工作,所以不知道它是否按需要链接或运行。)
SubscribeTimer( 1000, [this](){this->OnTimerA();} );
提到一个我已经放弃的替代方案:给Foo 一个超类,其中包含一个名为OnTimer() 的方法,该方法将在计时器关闭时调用。现在SubscribeTimer() 只需要经过一段时间。我不喜欢这样,因为它不允许注册多个计时器。如果是这样,您可以给他们(比如说)整数计时器 ID,并将 OnTimer() 实现为 switch,但这似乎比 C++99 解决方案复杂得多。
在(我假设的)几种方法中,除了涉及多少类型的最明显问题之外,是否有任何权衡(例如,堆使用)? (这是一个高性能应用程序,我希望尽量减少或消除堆使用。)
【问题讨论】:
-
阅读有关性能比较的信息:stackoverflow.com/questions/14306497/… tldr 引用已接受的答案:“C++11 的 std::function 调用仅增加了 2 条 CPU 指令,因此在我们的示例中为 5 条。作为结论:无论你使用哪种函数指针技术,开销差异都非常小。”
标签: c++11 c++14 c++17 std-function stdbind