9. Callback
9.1. 函数指针理解
在 C++ 里,函数指针分为两种:
普通函数指针:与 C 语言函数指针类似,静态的类成员函数指针也是该类型。
类成员函数指针(非静态)。
普通函数指针的使用与 C 语言里的函数指针使用一致,直接调用即可,例如:
typedef void (*func)(void);
func f;
f();
但是类成员函数指针(非静态)则不同了,区别在于该函数指针指向一个类成员函数,而该函数属于一个具体的类对象,需要在该对象的状态下调用该成员函数。
对于类成员函数的指针使用包含以下几个步骤:
声明: 指向类的成员函数的指针需要在指针前面加上类的类型,格式为:
typedef 返回值 (类名::*指针类型名)(参数列表);
赋值: 需要用类的成员函数地址赋值,格式为:
指针类型名 指针名 = &类名::成员函数名;
注意:这里的这个&符号是比较重要的:不加&,编译器会认为是在这里调用成员函数,所以需要给出参数列表,否则会报错;加了&,才认为是要获取函数指针。这是C++专门做了区别对待。
调用: 针对调用的对象是对象还是指针,分别用 .
和 ->
进行调用,格式为:
(类对象.*指针名)(参数列表);
(类指针->*指针名)(参数列表);
注意:这里的前面一对括号是很重要的,因为()的优先级高于成员操作符指针的优先级。
可以通过一个例程来理解:
class Calculation
{
public:
int add(int a,int b){ //非静态函数
return a + b;
}
};
typedef int (Calculation::*FuncCal)(int,int);
int main()
{
FuncCal funAdd = &Calculation::add;
Calculation * calPtr = new Calculation;
int ret = (calPtr->*funAdd)(1,2); //通过指针调用
Calculation cal;
int ret2 = (cal.*funAdd)(3,4); //通过对象调用
cout << "ret = " << ret << endl;
cout << "ret2 = " << ret2 << endl;
return 0;
}
9.2. Callback 引入
目前我对 Callback 的理解是:
mbed os 为了解决在给 API 传入类成员函数指针(非静态)时,API 无法知道该函数指针属于哪一个对象,因此就无法调用它。引入 Callback 模板类之后,就可以给 API 传入 Callback 对象,由 Callback 来管理类成员函数指针和它所属的对象,这样方便了 API 的设计。
例如:
_event_queue.call(Callback<void(bool)>(_button_service, &ButtonService::updateButtonState), true);
该语句指明了在 _button_service 对象里调用 updateButtonState 函数,即调用 _button_service.updateButtonState(true);
9.3. Callback 使用
TODO