目录
1.function
2。 150. 逆波兰表达式求值
编辑
C++11中提供了新的类模板function,它是一个包装器,可以包装其它可以存储调用其它的可调用对象,这里的可调用对象包括函数指针,仿函数,.lambda,bind表达式等,存储的可调用对象被称为function目标,若function不含目标,则城它为空,会抛出异常。
function的链接被包含在头文件
函数指针,仿函数,lambda等可调用对象的类型各不相同,function的优势就是统一类型,对它们都进行包装,这样在很多地方就可以方便使用可调用对象。
我们可以看到下面的例子,function说实话,它就是一个包装器,它把add函数包装成()形式去调用,但实际调用的还是原函数的地址,我们打印出两次调用add的地址发现它们相同,所以得出结论,function包装了add来进行()的统一调用,对于lambda,仿函数亦是如此。
#include
using namespace std;
#include
int add(int a, int b)
{
cout << add<f = add;
int b=f(1, 2);
return 0;
}
在文件中我们可以看到function实际上用了一个参数包和特化来实现。R是返回类型,参数包里是传参类型。下面我们再写一下仿函数,lambda的function包装怎么写。
这里其实我们function等号右边其实要写函数地址,只是普通函数函数名会自动取地址我们不用手动写,但是类中定义的普通成员函数需要写,这里C++对于类中的成员函数提供了两种方式,一种是传对象,一种是传对象地址,因为类中的普通成员函数第一个隐藏参数是this指针,方便知道是哪个对象调用了它,所以我们得给出对象或者对象地址。
至于lambda是这样写的function
类的成员函数我们分别写了对象和对象地址两种,c++对于这两种写法都是支持的,对象通过.*去回调成员函数,对象地址通过->去回调成员函数,所以支持了这两种写法。本质function它就是一个包装器,它对原函数没有改变,调用的函数还是原函数,只是包装成()统一调用了。
#include
int f(int a, int b)
{
return a + b;
}
struct Functor
{
public:
int operator() (int a, int b)
{
return a + b;
}
};
class Plus
{
public:
Plus(int n = 10)
:_n(n)
{}
static int plusi(int a, int b)
{
return a + b;
}
double plusd(double a, double b)
{
return (a + b) * _n;
}
private:
int _n;
};
int main()
{
// 包装各种可调⽤对象
function f1 = f;
function f2 = Functor();
function f3 = [](int a, int b) {return a + b; };
cout << f1(1, 1) << endl;
cout << f2(1, 1) << endl;
cout << f3(1, 1) << endl;
// 包装静态成员函数
// 成员函数要指定类域并且前⾯加&才能获取地址
function f4 = &Plus::plusi;
cout << f4(1, 1) << endl;
// 包装普通成员函数
// 普通成员函数还有⼀个隐含的this指针参数,所以绑定时传对象或者对象的指针过去都可以
function f5 = &Plus::plusd;
Plus pd;
cout << f5(&pd, 1.1, 1.1) << endl;
function f6 = &Plus::plusd;
cout << f6(pd, 1.1, 1.1) << endl;
cout << f6(pd, 1.1, 1.1) << endl;
function f7 = &Plus::plusd;
cout << f7(move(pd), 1.1, 1.1) << endl;
cout << f7(Plus(), 1.1, 1.1) << endl;
return 0;
}
这里我们如果传对象调用实际上去通过.*去回调成员函数了,编译器明白是哪个对象来调这个成员函数。我们给对象地址编译器也可以通过->去调用成员函数,所以这两种方法都是通过回调成员函数去调的。
obj.*
用于 对象实例 调用成员指针。obj->*
用于 对象指针 调用成员指针。#include
using namespace std;
class Student {
public:
string name;
int age;
Student(string n, int a) : name(n), age(a) {}
};
int main() {
Student s("Alice", 20);
Student* sPtr = &s;
// 定义成员变量指针
string Student::*namePtr = &Student::name;
int Student::*agePtr = &Student::age;
// 使用 obj.*
cout << "Name: " << s.*namePtr << ", Age: " << s.*agePtr << endl;
// 使用 obj->*
cout << "Name: " << sPtr->*namePtr << ", Age: " << sPtr->*agePtr << endl;
return 0;
}
class Solution {
public:
int evalRPN(vector& tokens) {
stacknums;
auto it = tokens.begin();
while (it != tokens.end())
{
if (*it == "+")
{
int tmp = nums.top();
nums.pop();
int tmp1 = nums.top();
nums.pop();
nums.push(tmp + tmp1);
}
else if (*it == "-")
{
int tmp = nums.top();
nums.pop();
int tmp1 = nums.top();
nums.pop();
nums.push(tmp1 - tmp);
}
else if (*it == "*")
{
int tmp = nums.top();
nums.pop();
int tmp1 = nums.top();
nums.pop();
nums.push(tmp1 * tmp);
}
else if (*it == "/")
{
int tmp = nums.top();
nums.pop();
int tmp1 = nums.top();
nums.pop();
nums.push(tmp1 / tmp);
}
else {
nums.push(stoi(*it));
}
it++;
}
return nums.top();
}
};
学了function和lambda之后我们可以简化代码,利用map的映射来解决问题:
class Solution {
public:
int evalRPN(vector& tokens) {
stack st;
// function作为map的映射可调⽤对象的类型
map> opFuncMap =
{
{"+", [](int x, int y){return x + y;}},
{"-", [](int x, int y){return x - y;}},
{"*", [](int x, int y){return x * y;}},
{"/", [](int x, int y){return x / y;}}
};
for(auto& str : tokens)
{
if(opFuncMap.count(str)) // 操作符
{
int right = st.top();
st.pop();
int left = st.top();
st.pop();
int ret = opFuncMap[str](left, right);
st.push(ret);
}
else
{
st.push(stoi(str));
}
}
return st.top();
}
};