c++11新特性下
- 一、前言
- 二、包装器
- 2.1包装器统一了接口
- 2.2使用包装的思想设计包装函数
- 三、绑定(bind)
- 3.1调整参数顺序
- 3.2调整参数个数
- 四、结语
一、前言
大家好久不见,今天我们继续来学习c++11的新特性。
二、包装器
先来看一段代码:
#include <iostream>
using namespace std;
class sub
{
public:
int operator()(int x, int y)
{
return x - y;
}
};
int add(int x, int y)
{
return x + y;
}
int main()
{
//函数指针: 1+2=3
int(*fp)(int, int);
fp = add;
cout << fp(1, 2) << endl;
//仿函数: 4-2=2
sub s;
cout << s(4,2) << endl;
//lambda表达式: 3*3=9
auto mul = [](int a, int b) -> int {
return a * b;
};
cout << mul(3, 3) << endl;
return 0;
}
在这段代码里,我分别使用了函数指针、仿函数、lambda表达式来表示加法,减法和乘法的运算,我们知道在C++中存在函数指针、仿函数和lambda表达式等多种方式来表示和使用函数,为什么还要费心费力地搞一个包装器出来呢,以下是我的个人理解:
2.1包装器统一了接口
假如我要将上述的三种运算保存在一个map里,你会发现这面临着重重困难,首先函数指针的类型及其复杂,再者三种运算都使用不同的方式实现,无法统一,也无法保证未来不使用新的方式实现,而包装器可以同时接收函数指针、仿函数、lambda表达式,调用时可以做到统一。
参考代码:
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
class sub
{
public:
int operator()(int x, int y)
{
return x - y;
}
};
int add(int x, int y)
{
return x + y;
}
int main()
{
map<string, function<int(int, int)>> opration_map;
opration_map =
{
{"+",add},
{"-",sub()},
{"*",[](int x,int y)->int {return x * y;} }
};
cout << opration_map["+"](2, 2) << endl; //4
cout << opration_map["-"](2, 2) << endl; //0
cout << opration_map["*"](2, 2) << endl; //4
}
2.2使用包装的思想设计包装函数
有了包装的思想,我们可以设计一个包装函数,可以统一管理和调用参数不一致、名称不一样的函数,当然也可以使用类似的思路设计对应的包装类。
#include <iostream>
#include <functional>
void internet_service(string ip,int port)
{
std::cout << "启动网络服务" << std::endl;
std::cout << "ip为:" << ip <<std::endl;
std::cout << "端口号为:" << port <<std::endl;
}
void process_service(int id) {
std::cout << "启动进程" << std::endl;
std::cout << "进程id:" << id <<std::endl;
}
// 统一接口的包装器函数
template<typename Func, typename... Args>
void execute(Func func, Args... args)
{
cout << "正在统一记录日志" << endl;
func(args...); // 调用原始函数
cout << "正在进行统一清理工作" << endl;
}
int main()
{
// 统一调用不同类型的函数
execute(internet_service, "127.0.0.1",8080);
execute(process_service,114514);
return 0;
}
三、绑定(bind)
3.1调整参数顺序
使用bind可以调整函数的参数顺序,实例如下:
void Print(int x,int y)
{
cout << "第一个参数:" << x << endl;
cout << "第二个参数:" << y << endl;
}
int main()
{
bind(Print, placeholders::_1, placeholders::_2)(1, 2);
bind(Print, placeholders::_2, placeholders::_1)(1, 2);
return 0;
}
3.2调整参数个数
我们知道类中的函数默认会带一个参数:this指针,这就会给我们的包装器带来诸多麻烦,因为又要去解决类型不一致的问题,恰巧bind能够帮助我们解决这个问题:
class sub
{
public:
int func(int x, int y)
{
return x - y;
}
};
int main()
{
sub s;
function<int(sub,int, int)> fsub1 = &sub::func;
function<int(int, int)> fsub2 = bind(&sub::func, sub(), placeholders::_1, placeholders::_2);
function<int(int, int)> fsub3 = bind(&sub::func, &s, placeholders::_1, placeholders::_2);
cout << fsub1(sub(), 2, 1) << endl;
cout << fsub2(2, 1) << endl;
cout << fsub3(2, 1) << endl;
return 0;
}
可以看到bind将第一个参数写死来减少实际需要我们传递的参数个数,可以看到使用bind无论是匿名对象还是实例指针都是可以成功绑定的,但第一种我们在调用的时候只能传递类的对象,因此更推荐第二种方式。
四、结语
到这里,关于c++11新特性的相关讲解就告一段落了,两篇文章间隔较长,主要是中间去做课设了,不过好在课设拿了95分,也算没白浪费时间,接下来会持续更新c++和Linux以及MySQL的相关知识,我们下期再见!