将类成员函数作为回调传递
在面向对象编程中,偶尔需要将类成员函数作为回调传递给一个外部API。但是,直接尝试此操作可能会遇到编译错误,如以下场景所示:
m_cRedundencyManager->Init(this->RedundancyManagerCallBack);
编译器抱怨函数指针缺少参数列表,建议改用 &CLoggersInfra::RedundancyManagerCallBack。然而,这仍然无法编译。
理解成员函数
在深入研究解决方案之前,了解成员函数的真正本质至关重要。在 C 中,成员函数本质上是具有附加隐藏参数的常规函数:this。这个隐藏参数代表该函数所属的对象实例。
考虑以下示例:
class A { public: int data; void foo(int addToData) { data += addToData; } };
函数 A::foo 采用一个参数,但在内部,它使用两个参数进行操作:addToData 和这个。后者指向调用 foo 的 A 对象。当使用成员函数语法 an_a_object.foo(5) 时,此行为是隐式的。从语法上讲,编译器将其翻译为 A::foo(&an_a_object, 5)。
回调问题
回到最初的问题,API 的 Init 函数期望带有单个参数的函数指针。然而,像 CLoggersInfra::RedundancyManagerCallBack 这样的类成员函数本质上需要两个参数,包括隐藏的 this 参数。这种不兼容会导致编译错误。
解决方案:使用 Boost 或 Lambda 函数绑定
传统的解决方案是使用 Boost 的 boost 将成员函数绑定到特定的类实例::bind 库或 C 11 的 lambda 函数。
使用 boost::bind,可以创建一个新函数,通过将隐藏的 this 参数“锁定”到特定的对象实例来获取所需的参数。然后这个新函数可以作为回调传递。
#include <boost/bind.hpp> auto bound_callback = boost::bind(&CLoggersInfra::RedundencyManagerCallBack, this); Init(boost::function<void()>(bound_callback));
C 11 提供 lambda 函数作为 boost::bind 的更简单替代方案。 Lambda 函数还可以捕获 this 指针,从而实现简洁的回调绑定:
auto lambda_callback = [this]() { RedundancyManagerCallBack(); }; Init(std::function<void()>(lambda_callback));
以上是如何将 C 类成员函数作为回调传递?的详细内容。更多信息请关注PHP中文网其他相关文章!