std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们。
下面的实例代码中演示了可调用对象包装器的基本使用方法:
//普通含税
void print(int num, string name) {
cout << "id:" << num << ",name:" << name << endl;
}
//抽象出对应的函数指针
//类型别名funcPtr,它代表一个指向接受一个int和一个string参数,并返回void的函数的指针
using funcPtr = void (*)(int, string);
//类
class Test {
public:
//重载()
void operator()(string msg) {
cout << "仿函数:" << msg << endl;
}
//将类对象转换为函数指针,此处转换的类型为funcPtr
operator funcPtr() {
return world;//return要转换的函数指针类型的实际函数地址
}
void hello(int a, string s) {//未定义类对象时,此函数不会存在
cout << "number:" << a << ",name:" << s << endl;
}
static void world(int a, string s) {//未定义类对象时,此函数就已经存在
cout << "number:" << a << ",name:" << s << endl;
}
int m_id = 520;
string m_name = "tom";
};
//包装普通函数
//包装的可调用对象的返回值为void,参数列表为int和string,打包后的名字为f2
function<void(int, string)> f2 = print;
f2(2, "f2");
//包装类中的静态函数
function<void(int, string)> f3 = Test::world;
f3(3, "f3");
//包装仿函数
Test t3;
function<void(string)> f4 = t3;
f4("f4");
//包装转换为函数指针的对象
Test t4;
function<void(int, string)> f5 = t4;
f5(5, "f5");
class A {
public:
//构造函数参数是一个包装器类型
A(const function<void(int, string)> &f) : callback(f) {}
void notify(int id, string name) {
callback(id, name);
}
private:
function<void(int, string)> callback;
};
A aa(print);
aa.notify(1, "aa");
A ab(Test::world);
ab.notify(2, "ab");
A ac(t4);
ac.notify(3, "ac");
完整代码:
#include <iostream>
#include <string>
#include<functional>
using namespace std;
//普通含税
void print(int num, string name) {
cout << "id:" << num << ",name:" << name << endl;
}
//抽象出对应的函数指针
//类型别名funcPtr,它代表一个指向接受一个int和一个string参数,并返回void的函数的指针
using funcPtr = void (*)(int, string);
//类
class Test {
public:
//重载()
void operator()(string msg) {
cout << "仿函数:" << msg << endl;
}
//将类对象转换为函数指针,此处转换的类型为funcPtr
operator funcPtr() {
return world;//return要转换的函数指针类型的实际函数地址
}
void hello(int a, string s) {//未定义类对象时,此函数不会存在
cout << "number:" << a << ",name:" << s << endl;
}
static void world(int a, string s) {//未定义类对象时,此函数就已经存在
cout << "number:" << a << ",name:" << s << endl;
}
int m_id = 520;
string m_name = "tom";
};
class A {
public:
//构造函数参数是一个包装器类型
A(const function<void(int, string)> &f) : callback(f) {}
void notify(int id, string name) {
callback(id, name);
}
private:
function<void(int, string)> callback;
};
int main() {
Test t;
t("abc");//使用类中重载的()操作符
Test t1;
t1(19, "make");//传递了两个参数,因为将t1对象转换为了函数指针,world函数被调用
//类的函数指针
funcPtr f = &Test::world;//静态函数
//定义指向类中非静态函数(hello)的指针
using fPtr = void (Test::*)(int, string);//Test::*表示属于Test的指针
fPtr f1 = &Test::hello;
//类的成员指针(变量)
using ptr1 = int Test::*;
ptr1 pt = &Test::m_id;
Test t2;
(t2.*f1)(20, "ace");//解引用*f1是一个函数,调用hello函数
t2.*pt = 100;//解引用*pt是一个int型变量
cout << "m_id:" << t2.m_id << endl;
//包装普通函数
//包装的可调用对象的返回值为void,参数列表为int和string,打包后的名字为f2
function<void(int, string)> f2 = print;
f2(2, "f2");
//包装类中的静态函数
function<void(int, string)> f3 = Test::world;
f3(3, "f3");
//包装仿函数
Test t3;
function<void(string)> f4 = t3;
f4("f4");
//包装转换为函数指针的对象
Test t4;
function<void(int, string)> f5 = t4;
f5(5, "f5");
A aa(print);
aa.notify(1, "aa");
A ab(Test::world);
ab.notify(2, "ab");
A ac(t4);
ac.notify(3, "ac");
return 0;
}
通过测试代码可以得到结论:std::function可以将可调用对象进行包装,得到一个统一的格式,包装完成得到的对象相当于一个函数指针,和函数指针的使用方式相同,通过包装器对象就可以完成对包装的函数的调用了。