可调用对象
以前函数调用总是离不开一堆圆括号,没错“()”就是函数调用的一个明显标记,这个 “()”有一个称呼叫函数调用运算符。
那么在类中重载了这个函数调用运算符“()”,就可以像使用函数一样是用那个该类的对象,或者换句话说就可以像函数调用一样来“调用”该类的对象
1.函数指针
创建一个.cpp文件然后加入以下代码
void myfunc(int tv) { cout << "myfunc()函数执行了,tv=" << tv << endl; }
在 main函数中加入如下代码
void(*pmf)(int) = myfunc; pmf(20);
2.具有 operator() 成员函数的类对象(仿函数/函数对象)
仿函数的定义:仿函数又称为函数对象,是一个能行使函数功能的类所定义的对象。防寒输得语法几乎和普通的函数调用一样。
在 cpp文件前面增加如下 TC类定义
class TC { public: void operator()(int tv) { cout << " TC::operator()执行了,tv=" << tv << endl; } };
在main函数中加入如下代码(可以选择将之前的main函数注释掉)
TC tc; tc(20);//调用的是()操作符,这就是个可调用对象。等价于tc.operator()(20);
3.可被转换为函数指针的类对象
可被转换为函数值指针的类对象也可以叫做 仿函数或函数对象
在 cpp文件中增加如下 TC2类定义
class TC2 { public: using tfpoint = void(*)(int); static void mtsfunc(int tv) //静态成员函数 { cout << "TC2::mysfunc()静态成员函数执行了,tv=" << tv << endl; } operator tfpoint() { return myfunc; }//类型转换运算符/类型转换函数 };
在main主函数中,加入如下代码
TC2 tc2; tc2(30);
4.类成员函数指针
在前面的 TC类中增加一个 public修饰的成员函数和一个成员变量
public: void ptfunc(int tv) { cout << "TC::ptfunc()执行了,tv=" << tv << endl; }; int m_a;
在 main主函数中加入如下代码
TC tc3; void(TC::*myfpoint)(int) = &TC::ptfunc;//类成员函数指针变量 myfpoint定义并被给初值 (tc3.*myfpoint)(999); //要调用你成员函数,就必须要用到对象 tc3
6.总结
可调用对象首先被看做一个对象。那么有没有一种方法能够把这些可调用对象的调用形式统一起来呢?有,那就是使用 std::function 把这些可调用对象包装起来。
std::function 可调用对象包装器
要使用这个类模板,在 cpp文件中要添加头文件 #include
这个蕾姆办理装的是各种可调用对象,比较遗憾的是不能装类成员函数指针。因为类成员函数指针是需要类对象参与才能完成调用的。
#include 类模板的特点是:**通过指定模板参数,它能够用统一的方式来处理各种可调用对象。
1.绑定普通函数
在 main 主函数中加入如下代码
//返回类型(参数列表) std::function<void(int)>f1 = myfunc;//绑定一个普通函数,注意<>中的格式 f1(100);//调用普通函数
2绑定类的静态成员函数
在前面的TC类中增加一个 public修饰的静态成员函数
static int stcfunc(int tv) { cout << "TC::stcfunc()静态函数执行了,tv=" << tv << endl; return tv; }
在 main函数中加入如下代码
//返回类型(参数列表) std::function<int(int)> fs2 = TC::stcfunc; fs2(110);
3绑定仿函数
在 main函数中,加入如下代码
TC tc3; std::function<void(int)> f3 = tc3;//提示使用了未初始化的局部变量“tc3”,因为类TC里有成员变量没被初始化,需要增加一个构造函数,还应该初始化一下成员变量才好
在 TC类中增加 public修饰的构造函数并初始化成员变量 m_a
TC() //构造函数 { m_a = 1; }//加入之后不会再报错了
在 main主函数中,继续增加代码
f3(120); //TC::operator()执行了, tv = 120 TC2 tc4; std::function<void(int)> f4 = tc4; f4(150); //TC2::mysfunc()静态成员函数执行了, tv = 150
4范例演示
在 cpp文件 前面增加如下 CB类和 CT类定义
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()//构造函数 { cout << "CT::CT()执行" << endl; } CT(const CT&)//拷贝构造函数 { cout << "CT::CT(const CT&)执行" << endl; } ~CT() { cout << "CT::~CT()执行" << endl; } void operator()(void) { cout << "CT::opertor()执行" << endl; } };
在 main函数中,加入如下代码:
CT ct; //可调用对象,这行导致CT构造函数的执行 CB cb(ct); //cb需要可调用对象做参数来构造,ct因为有operator()所以可以转为const std::function<void (void)> &对象。 //这行导致CT拷贝构造函数被执行多次 cb.runcallback(); //CT::opertor()执行
再来一个范例,在 cpp前面增加如下代码
void mycallback(int cs, const std::function<void(int)>& f) { f(cs); } void runfunc(int x) { cout << x << endl; }
在 main中函数中,加入如下代码:
for (int i = 0; i < 10; i++) { mycallback(i, runfunc);//0,1,2,3,4,5,6,7,8,9 }
从范例中可以看出 std::function 的灵活性非常高,能容纳的可调用对象种类也非常多。
C++高级开发之可调用对象、function、bind(2)https://developer.aliyun.com/article/1415895?spm=a2c6h.13148508.setting.24.16254f0exsfwiz