前言
使用callback常常需要绑定类的具体函数,哪些可以绑定哪些不能?
分析
callback不同与普通函数,其入参也是一个函数,具体行为由入参决定
我们看这样一段代码
https://godbolt.org/z/4YTKs567j
#include <functional>
#include <iostream>
class A
{
public:
void print(const int& m)
{
std::cout << "A::print: " << m << std::endl;
}
};
class B
{
public:
using CallbackType = std::function<void(const int&)>;
void set(const CallbackType& f)
{
function = f;
}
void run(const int& n)
{
if(function)
{
function(n);
}
}
private:
CallbackType function = nullptr;
};
void outPrint(const int& m)
{
std::cout << "outPrint: " << m << std::endl;
}
int main()
{
A a{};
B b{};
b.set(outPrint);
b.run(8);
// b.set(a.print); // won't compile
b.set(std::bind(&A::print,&a,std::placeholders::_1));
b.run(7);
return 0;
}
运行结果
ASM generation compiler returned: 0
Execution build compiler returned: 0
Program returned: 0
outPrint: 8
A::print: 7
其中outPrint()
作为外部函数很容易被掉用,比较好理解。
若尝试传入a.print()
会报错
<source>: In function 'int main()':
<source>:44:18: error: invalid use of non-static member function 'void A::print(const int&)'
b.set(a.print); // won't compile
^
<source>:7:6: note: declared here
void print(const int& m)
^~~~~
Compiler returned: 1
一般看到这里会把A::print()
注册为static方法使其脱离A成为独立函数,如果A::print()
适用了A中其他变量也都需要声明为static类型,也许这能够解决问题,但本质上不能传入的原因是因为A::print()
需要两个入参,第一个为编译器隐式传入的thisz指针,因此可以使用std::bind
固化部分参数完成函数特化。
总结
对于无法callback的报错不要盲目修改static尽量适用std::bind
的方式对函数进行特化减少入参。