前言
之前在复习C++的基础知识和了解C++11的新特性时,总会遇到可调用对象和函数对象这两个概念。参考了网上部分资料,自己整理记录下。
一、可调用对象
各种可调用的实体,即通过()来调用,主要包括普通函数、Lambda表达式、函数指针、类成员函数、仿函数(重载了()运算符的类对象)等。具体如下
(1)普通函数(没啥好讲的)
(2)Lambda表达式
auto lambda = [](int a)->int{return a;};
关于lambda捕获域的介绍,这里不做展开。
(3)仿函数
class Functor
{
public:
int operator()(int a)
{
return a;
}
};
因此,C++11的线程入口也可以使用仿函数类的对象。
(4)类的普通成员函数和静态成员函数
二、std::function
首先这是一个模板,他的申明方式和函数指针类似。他的使用方式就是通过std::function对C++中各种可调用对象(上述这些)的封装,形成一个新的可调用的std::function对象,让我们不在纠结于那么多的可调用实体。例如
std::function< int(int)> Functional;
// Lambda表达式
auto lambda = [](int a)->int{ return a; };
// 普通函数
int TestFunc(int a)
{
return a;
}
// 1.类成员函数
// 2.类静态函数
class TestClass
{
public:
int ClassMember(int a) { return a; }
static int StaticMember(int a) { return a; }
};
int main()
{
// 普通函数
Functional = TestFunc;
int result = Functional(10);
cout << "普通函数:"<< result << endl;
// Lambda表达式
Functional = lambda;
result = Functional(20);
cout << "Lambda表达式:"<< result << endl;
// 类成员函数
TestClass testObj;
Functional = std::bind(&TestClass::ClassMember, testObj, std::placeholders::_1);
result = Functional(40);
cout << "类成员函数:"<< result << endl;
// 类静态函数
Functional = TestClass::StaticMember;
result = Functional(50);
cout << "类静态函数:"<< result << endl;
return 0;
}
std::function对象最大的用处就是在实现函数回调。
三、std::function于std::bind实现函数回调
(1)std::bind函数原型
bind(_Func&& __f, _BoundArgs&&... __args)
作用:将函数对象于参数绑定并返回一个绑定后的函数对象(std::function类型)。第一个参数__f指定一个函数对象,__args是不定长参数,用于将指定参数传入对象中。注意:上述的函数对象如果是指类成员函数,则___args中的第一个参数必须是调用该函数的首地址,即:this指针。若传入的参数是不定的,也就是说该参数可能随着程序的运行而变化,那么参数就得按以下方式进行设置。
std::placeholders::_n
这里的 _n,可以是 _1、_2、……,分别代表第 1 个参数、第 2 个参数、……若是定值,即:该参数不会随着程序的变化而变化,那么直接填入相应值即可。
(2)回调的具体实现
// 定义回调函数类型
typedef std::function<void(int,const char*)> MeaasgeFun;
// 定义函数对象
class ThreadObject
{
public:
ThreadObject()
{
m_MessageEvent=NULL;
}
void setMessageEvent(MessageFun event)
{
m_MessageEvent=event;
}
private:
MessageFun m_MessageEvent;
void run();
}
// 任务执行完毕调用回调
void ThreadObject::run()
{
//执行任务
...
//执行完毕调用函数对象通知
if(m_MessageEvent)
m_MessageEvent(1,"Ok");
}
// 在主线程中定义回调函数处理函数
class MainObject
{
public:
MainObject();
private:
ThreadObject m_thread;
void onMessageEvent(int status,const char *msg);
}
void MainObject::onMessageEvent(int status,const char *msg)
{
if(status==1)
cout<<msg;
}
// 设置回调函数
MainObject::MainObject()
{
m_thread.setMessageEvent(std::bind(&MainObject::onMessageEvent,this,std::placeholders::_1,std::placeholders::_2));
}
实际上的原理和Qt的信号于槽是类似的,有空可以讲下Qt信号于槽的底层实现。未完待续.....