1.包装器
C++中有一些可调用对象,比如 函数指针,仿函数对象 lambda等等,但是他们又有缺点
因此就引出了包装器的概念
包装器 function的头文件是<functional>
我们可以用包装器包装函数指针,仿函数,lambda
int f(int a, int b)
{
return a + b;
}
struct functor
{
int operator()(int a, int b)
{
return a + b;
}
};
int main()
{
//包装函数指针
function<int(int, int)> f1 = f;
cout << f1(10, 20) << "\n";
//包装仿函数
function<int(int, int)>f2 = functor();
cout << f2(10, 20) << "\n";
//包装lambda
function<int(int, int)>f3 = [](int a, int b) {return a + b; };
cout << f3(10, 20) << "\n";
return 0;
}
用包装器解决逆波兰表达式
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
map<string,function<int(int,int)>>Map={
{"+",[](int a,int b){return a+b;}},
{"-",[](int a,int b){return a-b;}},
{"*",[](int a,int b){return a*b;}},
{"/",[](int a,int b){return a/b;}}
};
for(auto& e:tokens)
{
if(Map.count(e))
{
int right=st.top();
st.pop();
int left=st.top();
st.pop();
st.push(Map[e](left,right));
}
else
{
st.push(stoi(e));
}
}
return st.top();
}
};
如果包装成员函数指针,需要注意哪些?
对于成员函数,要传this指针,使参数匹配,如果是静态成员函数,则没有this指针,要注意区分
class Plus
{
public:
static int plusi(int a, int b)
{
return a + b;
}
double pulsd(double a, double b)
{
return a + b;
}
};
int main()
{
//对于静态成员函数,没有this指针,传参时可以不用传this指针
function<int(int, int)> f1 = &Plus::plusi;
cout << f1(10, 20) << "\n";
//对于成员函数,需要传this指针,要求类型匹配
//这里有两种写法,一种是传对象指针,一种是传对象
function<double(Plus*,double, double)> f2 = &Plus::pulsd;
Plus plus;
cout << f2(&plus, 10, 20) << "\n";
function<double(Plus, double, double)> f3 = &Plus::pulsd;
cout << f3(Plus(), 10, 20) << "\n";
return 0;
}
2.bind
std::bind定义在<functional>头文件里,是一个函数模板,他可以接受一个可调用对象,然后生成一个新的可调用对象,新的可调用对象的参数顺序或者参数个数可以发生改变,以此来适应原对象的参数列表,
int add(int a, int b)
{
return a + b;
}
class Sub
{
public:
int sub(int a, int b)
{
return (a - b);
}
};
int main()
{
//普通函数绑定
auto f1 = bind(add, placeholders::_1, placeholders::_2);
cout << f1(10, 20) << "\n";
//成员函数绑定,要传this指针
auto f2 = bind(&Sub::sub, placeholders::_1, placeholders::_2, placeholders::_3);
Sub s1;
cout << f2(&s1,20, 10) << "\n";
//可以绑定this指针,然后就不需要再传this指针了,减少了传参个数
Sub s2;
auto f3 = bind(&Sub::sub, &s2,placeholders::_1, placeholders::_2);
cout << f3(20, 10) << "\n";
return 0;
}
bind的函数传参表示的含义,比如:
auto f3 = bind(&Sub::sub, &s2,placeholders::_1, placeholders::_2);
&Sub::sub :表示指定函数的地址,对于普通函数不需要加&符号,因为函数名就是地址,对于成员函数则需要加&符号;
&s2:表示成员函数的this指针,如果绑定的不是成员函数,则不需要写;
placeholders::_1, placeholders::_2 :表示需要传的参数;
bind还可以调换参数顺序
也就是说placeholders::_1永远表示传的第一个参数,placeholders::_2表示传的第二个参数,而对于fx函数来说,按照传参顺序,placeholders::_2表示a,placeholders::_1表示b,这样就实现了参数顺序的调换;