C++11回调函数与注意事项
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
回调函数可以是静态类函数
也可以是全局函数
。
回调函数机制:
- 定义一个函数(普通函数即可);
- 将此函数的地址注册给调用者;
- 特定的事件或条件发生时,调用者使用函数指针调用回调函数
注意事项
- 全局函数可以直接作为回调函数
- C++将类函数直接作为回调函数,必须是静态函数
原因
:大概原因是普通的C++成员函数都隐含了一个传递函数作为参数,即this指针,C++通过传递this指针给成员函数从而实现函数可以访问C++的数据成员。由于this指针的原因,使得一个普通成员函数作为回调函数时就会因为隐含的this指针问题使得函数参数个数不匹配,从而导致回调函数编译失败。
原文链接
注:C++静态成员函数
- 与静态数据成员不同,静态成员函数的作用不是为了对象之间的沟通,而是为了能处理静态数据成员。
静态成员函数没有this
指针。既然它没有指向某一对象,也就无法对一个对象中的非静态成员进行默认访问(即在引用数据时不指定对象名)。
静态成员函数和非静态成员函数的根本区别:
非静态成员函数有this指针,而非静态成员函数没有this指针。由此决定了静态成员函数不能访问本类中的非静态成员。
静态成员函数可以直接引用本类中的静态数据成员,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。
原文链接
使用方法
全局函数-C写法
#include <stdio.h>
typedef int(*callback)(int, int);
int add(int a, int b, callback p){
return (*p)(a, b);
}
int add(int a, int b){
return a + b;
}
int main(int argc, char *args[]){
int res = add(4, 2, add);
printf("%d\n", res);
return 0;
}
全局函数-C++写法1-(推荐写法)
#include <iostream>
typedef int(*callback)(int, int);
int add(int a, int b)
{
return a + b;
}
int Print(callback p, int a, int b)
{
std::cout << p(a, b) << std::endl;
return 0;
}
int main()
{
Print(add, 1, 2);
system("pause");
return 0;
}
全局函数-C++写法2
#include <iostream>
int add(int a, int b)
{
return a + b;
}
int Print(int(*callback)(int, int), int a, int b)
{
std::cout << callback(a, b) << std::endl;
return 0;
}
int main()
{
Print(add, 1, 2);
system("pause");
return 0;
}
静态类函数
- 无需指明类对象
- 只能访问到类的静态变量,(除非将调用对象作为参数传入静态函数,
不推荐
)链接举例
#include <iostream>
typedef int(*callback)(int);
class classA
{
public:
static int classA::m_i;
static int classA_cb(int i)//静态函数没有this指针,只能访问到静态成员
{
m_i = 0;
std::cout << i << std::endl;
return m_i;
};
};
int classA::m_i = 0; //静态成员是该类所有对象唯一的,静态成员使用之前必须初始化
int test(callback p, int i)
{
return p(i);
}
int main()
{
std::cout << test(classA::classA_cb, 1) << std::endl;//因为函数是静态的,所以,使用方式类似全局函数
system("pause");
return 0;
}
非静态类函数-指定类并提供调用的对象
非静态函数,必须指定函数所在类,然后传入类的对象。如果是类调用自身的非静态成员函数,则不需要传入对象。
#include <iostream>
class MyClass;
typedef void (MyClass::*CallbackFunc)(int); // 声明回调成员函数指针
class MyClass
{
public:
void Func(int n)// 回调成员函数
{
std::cout << __FUNCTION__ << " n = " << n << std::endl;
}
void test(CallbackFunc func, int n)// 在类的内部调用
{
(this->*func)(n);
}
};
void test(CallbackFunc func, MyClass *obj, int n)// 在类的外部调用
{
(obj->*func)(n);
}
int main()
{
MyClass obj;
obj.test(&MyClass::Func, 10);//使用类调用类内的函数的方式
test(&MyClass::Func, &obj, 20);//使用类外调用类内函数的方式
system("pause");
return 0;
}
非静态成员函数-模板方式实现
#include <iostream>
class MyClass
{
public:
void Func(int n)// 回调成员函数
{
std::cout << __FUNCTION__ << " n = " << n << std::endl;
}
};
class OtherClass
{
public:
void Func(int n)// 回调成员函数
{
std::cout << __FUNCTION__ << " n = " << n << std::endl;
}
};
template<typename T, typename A>
void test(void (T::*method)(A), T *obj, const A& a)
{
(obj->*method)(a);
}
int main()
{
MyClass obj;
test(&MyClass::Func, &obj, 10);
OtherClass other;
test(&OtherClass::Func, &other, 20);
system("pause");
return 0;
}
声明函数指针数组
template <typename PanelClass>
typedef void(PanelClass::*FlashAllAreaCB[10])();
声明函数指针容器-存疑
//会报错,不知为啥
template <typename PanelClass>
typedef void(PanelClass::*FlashAllAreaCB[10])();
std::list<FlashAllAreaCB> mylist;//提示FlashAllAreaCB未定义
示例1-类模板+回调函数
#include <iostream>
#include <list>
class panelClass
{
public:
void Func1()// 回调成员函数
{
std::cout << __FUNCTION__ << " n = " << std::endl;
}
};
template<typename T>
class classA
{
typedef void(T::*callback)();
T * mobj;
callback mcb;
public:
classA(callback cb, T * obj);
void flushs();
};
template<typename T>
classA<T>::classA(callback cb, T * obj)
{
mcb = cb;
mobj = obj;
}
template<typename T>
void classA<T>::flushs()
{
(mobj->*mcb)();
}
int main()
{
panelClass pc;
classA<panelClass> ca(&panelClass::Func1, &pc);
ca.flushs();
system("pause");
return 0;
}
示例2-类模板+回调函数
- 一个类
classA
中声明另一个类panelClass
- 向
panelClass
中填入需要由其调用的回函数Func1
- 在需要的时候,
panelClass
会代替classA
调用Func1
函数(例如多线程定时调用)
#include <iostream>
#include <list>
template<typename T>
class classA
{
typedef void(T::*callback)();
T * mobj;
callback mcb;
public:
classA(callback cb, T * obj) :mcb(cb), mobj(obj){};
void flushs(){ (mobj->*mcb)(); };
};
class panelClass
{
public:
panelClass(){ ca = new classA<panelClass>(&panelClass::Func1, this); };
~panelClass(){ delete ca; ca = NULL; };
classA<panelClass> * ca;
void Func1()// 回调成员函数
{
std::cout << __FUNCTION__ << " n = " << std::endl;
}
};
int main()
{
panelClass pc;
pc.ca->flushs();
system("pause");
return 0;
}