前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++11第四弹:包装器

C++11第四弹:包装器

作者头像
南桥
发布2024-09-16 08:18:02
970
发布2024-09-16 08:18:02
举报
文章被收录于专栏:南桥谈编程

包装器

包装器是一个类模板

C++中的可调用对象:函数指针(类型定义很复杂)、仿函数对象(定义一个类的时候,用的时候有些麻烦,其次不适合统一类型)、lambda(没有类型概念)、包装器

function包装器

function包装器 也叫作适配器。C++中的function本质是一个类模板,也是一个包装器。

std::function在头文件<functional> 类模板原型:

代码语言:javascript
复制
template <class T> function; // undefined
template <class Ret, class... Args>
class function<Ret(Args...)>;

模板参数说明: Ret: 被调用函数的返回类型 Args…:被调用函数的形参

他不是用来定义可调用对象,是用来包装可调用对象:

代码语言:javascript
复制
#include<functional>

int f(int a, int b)
{
	return a + b;
}

struct Functor
{
public:
	int operator() (int a, int b)
	{
		return a + b;
	}
};

int main()
{
	function<int(int, int)> fc1;
	//包装函数指针
	function<int(int, int)> fc2 = f;
	cout << fc2(1, 2) << endl;
	//包装仿函数
	function<int(int, int)> fc3 = Functor();
	cout << fc3(2, 3) << endl;
	//包装lambda表达式
	function<int(int, int)> fc4 = [](int x, int y) {return x + y; };
	cout << fc4(3, 4) << endl;

	return 0;
}
应用场景

力扣:150.逆波兰表达式求值

代码语言:javascript
复制
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;

        //命令和对应的函数动作结合
        map<string,function<int(int,int)>> opfuncMap={
            {"+",[](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& str:tokens)
        {
            if(opfuncMap.count(str)) // 是操作符
            {
                function<int(int,int)> func=opfuncMap[str];
                int right=st.top();
                st.pop();
                int left=st.top();
                st.pop();
                st.push(func(left,right));
                
            }
            else //是操作数 
            {
                st.push(stoi(str));
            }
        }
        return st.top();
    }
};
包装成员函数指针

在包装静态成员指针函数时,当我们需要用到某个函数时,需要在前面指定类域。但如果不是静态时,不仅需要添加类域,还需要添加一个&

代码语言:javascript
复制
class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}
	double plusd(double a, double b)
	{
		return a + b;
	}
};

int main()
{
	function<int(int, int)> fc1 = Plus::plusi;
	cout << fc1(1, 2) << endl;

	function<double(Plus*, double, double)> fc2 = &Plus::plusd;
	Plus plus;
	cout << fc2(&plus, 1.1, 2.2) << endl;
	
	function<double(Plus, double, double)> fc3 = &Plus::plusd;
	//Plus plus;
	cout << fc3(Plus(), 1.1, 2.2) << endl;

	return 0;
}

fc1 是一个 std::function<int(int, int)> 对象,绑定到静态成员函数 Plus::plusi。调用 fc1(1, 2) 输出 3

fc2 是一个 std::function<double(Plus*, double, double)> 对象,绑定到非静态成员函数 Plus::plusd。它接受一个 Plus* 指针和两个 double 类型的参数。调用 fc2(&plus, 1.1, 2.2) 计算 1.1 + 2.2 并输出 3.3

bind

std::bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器),接受一个可调用对象(callable object),生成一个新的可调用对象来“适应”原对象的参数列表。一般而言,我们用它可以把一个原本接收N个参数的函数fn,通过绑定一些参数,返回一个接收M个(M可以大于N,但这么做没什么意义)参数的新函数。同时,使用std::bind函数还可以实现参数顺序调整等操作。

原型:

代码语言:javascript
复制
template <class Fn, class... Args>
bind (Fn&& fn, Args&&... args);
with return type (2)	
template <class Ret, class Fn, class... Args>
bind (Fn&& fn, Args&&... args);

可以将bind函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

调用bind的一般形式:auto newCallable = bind(callable,arg_list);

调整参数顺序
代码语言:javascript
复制
int Sub(int a, int b)
{
	return a - b;
}

int main()
{
	auto f1 = Sub;
	cout << f1(10, 5) << endl;

	auto f2 = bind(Sub, placeholders::_2, placeholders::_1);
	cout << f2(10, 5) << endl;

	return 0;
}
调整参数个数
代码语言:javascript
复制
class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};

int main()
{
	Sub sub;
	auto f3 = bind(&Sub::sub, Sub(), placeholders::_2, placeholders::_1);
	cout << f3(10, 5) << endl;

	return 0;
}

参数顺序:bind(&Sub::sub, &s, _2, _1) 绑定了成员函数 sub s 对象,并指定 _2_1 的位置。调用 f3(10, 5) 会将 5 映射到 _210 映射到 _1,因此 f3(10, 5) 实际上会调用 s.sub(5, 10),结果是 5 - 10,即 -5

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-09-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 包装器
    • function包装器
      • 应用场景
      • 包装成员函数指针
    • bind
      • 调整参数顺序
      • 调整参数个数
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档