文章目录
1.可调用对象
1.1 函数指针
void myfunc(int tv)
{
cout<<"myfunc()函数执行了,tv"<<tv<<std::endl;
}
//主函数main
void(*pmf)(int) = myfunc;//定义函数指针并给初值,myfunc也可以写成&myfunc,是一样的效果
pmf(15); //调用函数,这就是一个可调用对象
1.2 具有operator()成员函数的类对象(仿函数/函数对象)
class TC
{
public:
void operator()(int tv)
{
std::cout<<"TC::operator()执行了,tv = "<<tv<<std::endl;
}
};
//主函数
TC tc;
tc(20); //调用的是()函数,这是一个可调用对象,等价于tc.operator()(20);
1.3 可被转换为函数指针的类对象
class TC2
{
public:
using tfpoint = void(*)(int);//定义tfpoint是void类型函数且参数为int类型的函数指针
static void mysfunc(int tv)
{
cout<<"TC2::mysfunc()静态成员函数执行了,tv = "<<tv<<std::endl;
}
operator tfpoint(){return mysfunc;}//类型转换运算符/类型转换函数
};
//主函数
TC2 tc2;
tc2(50);//先调用tfpoint,再调用mysfunc;这就是一个可调用对象,等价于tc2.operator TC2::tfpoint()(50);
1.4 类成员函数指针
//class TC里面
void ptfunc(int tv)
{
std::cout<<"TC::ptfunc()执行了,tv = "<<tv<<std::endl;
}
int m_a;
//主函数
TC tc3;
void(TC:: *myfpointpt)(int) = &TC::ptfunc;//类成员函数指针变量myfpointpt定义并被给初值
(tc.*myfpointpt)(68); //要调用函数,就必须用到对象tc3
1.5 总结
- std::function可以把这些可调用对象的调用形式统一一下
2.std::function可调用对象包装器
2.1 绑定普通函数
std::function<void(int)> f1 = myfunc;//绑定一个普通函数myfunc,注意<>中的格式
f1(100); //调用普通函数
2.2 绑定类的静态成员函数
- TC类中增加一个Public修饰的静态成员函数
public:
static int stcfunc(int tv)
{
cout<<"TC::stcfunc()静态函数执行了,tv = "<<tv<<std::endl;
return tv;
}
//main函数
std::function<int(int)> f3 = TC::stcfunc();//绑定一个类的静态成员函数
fs2(110); //调用静态成员函数
2.3 绑定仿函数
- 例一
class TC
{
public:
TC()
{
m_a = 1;
}
void operator()(int tv)
{
std::cout<<"TC::operator()执行了,tv = "<<tv<<std::endl;
}
void ptfunc(int tv)
{
std::cout<<"TC::ptfunc()执行了,tv = "<<tv<<std::endl;
}
int m_a;
};
//主函数
TC tc3;
std::function<void(int)>f3 = tc3;
- 例二
class TC2
{
public:
using tfpoint = void(*)(int);//定义tfpoint是void类型函数且参数为int类型的函数指针
static void mysfunc(int tv)
{
cout<<"TC2::mysfunc()静态成员函数执行了,tv = "<<tv<<std::endl;
}
operator tfpoint(){return mysfunc;}//类型转换运算符/类型转换函数
};
//主函数
TC tc3;
std::function<void(int)>f3 = tc3;
f3(120);//执行了void operator()(int tv)
TC2 tc4;
std::function<void(int)>f4 = tc4;//
f4(120); //TC2::mysfunc()静态成员函数执行了,tv = 150
2.4 范例演示
- 范例一
class CB
{
std::function<void()>fcallback;
public:
CB(const std::function<void()>&f)
: fcallback(f)
{
int i;
i = 1;
}
void runcallback(void)
{
fcallback();
}
};
class CT
{
public:
CT() //构造函数
{
std::cout<<"CT::CT()执行"<<std::endl;
}
CT(const CT&) //拷贝构造函数
{
std::cout<<"CT::CT(const CT&)执行"<<std::endl;
}
void operator()(void)
{
std::cout<<"CT::operator()执行"<<std::endl;
}
};
int main()
{
CT ct; //可调用对象,这行导致CT构造函数的执行
CB cb(ct); //cb需要可调用对象作为参数来构造,因为有operator()所以ct可以转为const std::function<void(void)>&对象
//这行导致CT拷贝构造函数被执行多次
cb.runcallback(); //CT::operator()执行
return 0;
}
- 范例二
void mycallback(int cs,const std::function<void(int)>&f)
{
f(cs);
}
void runfunc(int x)
{
cout<<x;
}
int main()
{
for(int i = 0;i<10;++i)
{
mycallback(i,runfunc);
}
cout<<endl;
return 0;
}
3.std::bind绑定器
3.1 使用模板一般如下
std:;bind(待绑定的函数对象/函数指针/成员函数指针,参数绑定值1,参数绑定值2,。。。参数绑定值n);
3.2 std::bind定义分类
- 1)将可调用对象和参数绑定到一起,构成一个仿函数,所以可以直接调用
- 2)如果函数有多个参数,可以绑定部分参数,其他的参数再调用时指定
3.3 std::bind调用案例
一:
void myfunc1(int x,int y,int z)
{
cout<<"x = " <<x<<",y = "<<y<<",z = "<<z<<endl;
}
//主函数
auto buf1 = std::bind(myfunc1,10,20,30);
bf1();//执行myfunc1函数,结果:x = 10;y = 20;z=30
二:
auto bf2 = std::bind(myfunc1,placeholders::_1,placeholders::_2,30);
bf2(5,15); //x=5,y=15,z=30
//直接调用也可以
std::bind(myfunc1,placeholders::_1,placeholders_2,30)(10,20);//x=10,y=20,z=30
三:
void myfunc2(int&x,int& y)
{
x++;
y++;
}
int a = 2;
int b = 3;
auto bf4= std::bind(myfunc2,a,placeholders::_1);
bf(b);
四:绑定类成员函数
class CQ
{
public:
void myfunpt(int x,int y)
{
cout<<"x="<<x<<",y="<<y<<endl;
m_a = x;
}
int m_a = 0;//成员变量
};
//main主函数
CQ cq;
auto bf5 = std::bind(&CQ::myfunpt,&cq,placeholders::_1,placeholders::_2);//cq加&表示的就是不会生成临时对象
bf5(10,20); //对成员函数的调用
五:绑定成员变量
class CQ
{
public:
void myfunpt(int x,int y)
{
cout<<"x="<<x<<",y="<<y<<endl;
m_a = x;
}
CQ()
{
printf("CQ::CQ()构造函数执行,this = %p\n",this);
}
CQ(const CQ&)
{
printf("CQ::CQ(const CQ&)拷贝构造函数执行,this = %p\n",this);
}
~CQ()
{
printf("CQ::~CQ()析构函数执行,this = %p\n",this);
}
int m_a = 0;//成员变量
};
//main
CQ cq;
std::function<int&(void)>bf7 = std::bind(&CQ::m_a,&cq);
bf7() = 60;
4.总结
- 1.std::bind的思想实际上是一种延迟计算的思想,将可调用对象保存起来,然后在需要的时候再调用
- 2.std::function一般要绑定一个可调用对象,类成员函数不能被绑定。而std::bind更加强大,什么都能绑定。