C++ 包装器—function

发布时间:2024年01月02日

????? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???????????????🎬慕斯主页修仙—别有洞天

? ?????????????????????????????????????????????????????????今日夜电波:Duvet—B?a

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2:20━━━━━━?💟──────── 3:22
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????🔄 ? ?? ? ? ? ?? ? ????

??????????????????????????????????????💗关注👍点赞🙌收藏您的每一次鼓励都是对我莫大的支持😍


目录

一、什么是function?

二、function使用详解

包装基本的函数(普通、仿函数、lambda)

包装静态成员函数

包装普通成员函数

三、bind使用详解

调整参数的顺序

调整参数个数,用bind写死参数

用bind调整来包装成员函数


一、什么是function?

????????在C++中,std::function是一种模板类,它用于表示任意类型的函数或方法,可以作为函数参数或返回类型。std::function的提出可以用于替代函数指针,以此来降低使用回调函数的难度,它比普通函数指针更加的灵活和便利。

????????std::function的主要特点包括:

  • 可以存储和执行任何类型的函数或方法,只要该函数或方法能够被复制(即它可以有一个副本)。
  • 可以方便地对函数进行比较、拷贝、移动等操作。
  • 可以通过std::bind函数或其他方式创建具有特定参数和返回类型的函数实例。
template< class R, class... Args >
  class function<R(Args...)>;

对于以上各个部分的解析:

????????R表示函数的返回类型,Args表示函数的参数列表。std::function模板类生成的类可以用来存储任何符合这些类型的函数。

一个简单的例子:

#include <iostream>
#include <functional>

// 定义一个简单的函数
int add(int a, int b) {
    return a + b;
}

int main() {
    // 创建一个std::function实例,存储add函数
    std::function<int(int, int)> func = add;

    // 使用std::function执行add函数
    int result = func(1, 2);
    std::cout << "Result: " << result << std::endl;

    return 0;
}

????????在这个例子中,我们首先定义了一个简单的函数add,然后使用std::function创建了一个函数实例func,并将其初始化为add函数。最后,我们使用func执行add函数,并输出结果。

需要注意的是,std::function并不是C++标准库的一部分,而是C++11引入的新特性之一。因此,在使用std::function之前,需要确保你的编译器已经支持C++11或更高版本。

????????对以上例子进行详细的分析:function的R的定义是根据add函数的返回类型定义为int,函数的参数列表为两个int也是因为add函数的两个传参为int。

二、function使用详解

包装基本的函数(普通、仿函数、lambda)

#include<iostream>
#include<functional>
#include<string>
#include <map>
using namespace std;

//普通函数
void swap_func(int& r1, int& r2)
{
	int tmp = r1;
	r1 = r2;
	r2 = tmp;
}
//仿函数
struct Swap
{
	void operator()(int& r1, int& r2)
	{
		int tmp = r1;
		r1 = r2;
		r2 = tmp;
	}
};

int main()
{
	int x = 0, y = 1;
	cout << x << " " << y << endl;

//lambda
	auto swaplambda = [](int& r1, int& r2) {
		int tmp = r1;
		r1 = r2;
		r2 = tmp;
	};

	function<void(int&, int&)> f1 = swap_func;
	f1(x, y);
	cout << x << " " << y << endl << endl;

	function<void(int&, int&)> f2 = Swap();
	f2(x, y);
	cout << x << " " << y << endl << endl;

	function<void(int&, int&)> f3 = swaplambda;
	f3(x, y);
	cout << x << " " << y << endl << endl;

	map<string, function<void(int&, int&)>> cmdOP = {
		{"函数指针", swap_func},
		{"仿函数", Swap()},
		{"lambda", swaplambda},
	};

	cmdOP["函数指针"](x, y);
	cout << x << " " << y << endl << endl;

	cmdOP["仿函数"](x, y);
	cout << x << " " << y << endl << endl;

	cmdOP["lambda"](x, y);
	cout << x << " " << y << endl << endl;

	return 0;
}

包装静态成员函数

????????包装静态成员函数,我们需要指定类域,然后加上&用于成员函数取地址,当然因为是静态成员函数其实可以不加&,但是为了统一,我们最好加上。

class Plus
{
public:
	static int plusi(int a, int b)
	{
		return a + b;
	}

};

int main()
{
	// 成员函数取地址,比较特殊,要加一个类域和&
	function<int(int, int)> f1 = &Plus::plusi;
	cout << f1(1, 2) << endl;

	return 0;
}

包装普通成员函数

????????由于普通成员函数的包装还存在一个this,因此function中还需要传this,因此我们可以像以下的两种方式包装:一、传递指针,用指针去调用成员函数指针。二、传递对象,用对象去调用函数指针。(第二种可以理解成做了特殊处理)

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)> f1 = &Plus::plusi;
	cout << f1(1, 2) << endl;

	function<double(Plus*, double, double)> f2 = &Plus::plusd;
	Plus ps;
	cout << f2(&ps, 1.1, 2.2) << endl;

	function<double(Plus, double, double)> f3 = &Plus::plusd;
	cout << f3(Plus(), 1.11, 2.22) << endl;

	return 0;
}

三、bind使用详解

// 原型如下:
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2)
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);

????????bind函数用于将一个可调用对象(如函数、lambda表达式等)与一组参数绑定,生成一个新的可调用对象。

????????第一个模板声明template <class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args);表示bind函数接受一个可调用对象fn和一组参数args,返回一个新的可调用对象。其中,Fn是可调用对象的类型,Args是参数的类型,...表示可变参数包。

????????第二个模板声明template <class Ret, class Fn, class... Args> /* unspecified */ bind (Fn&& fn, Args&&... args);表示bind函数接受一个可调用对象fn、一个返回类型Ret和一组参数args,返回一个新的可调用对象。其中,Ret是返回类型的类型,Fn是可调用对象的类型,Args是参数的类型,...表示可变参数包。

调整参数的顺序

????????如下我们可以用function进行bind改变函数传参的顺序,根据(placeholder::_第几个参数)来按照对应的位置调整顺序。如下:

int Sub(int a, int b)
{
	return a - b;
}

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

	// 调整参数顺序
	function<int(int, int)> f2 = bind(Sub, placeholders::_2, placeholders::_1);
	cout << f2(10, 5) << endl;
    return 0;
}

调整参数个数,用bind写死参数

????????我们也可以用function进行bind通过写死一些参数来调整参数的个数,当然我们也是需要用(placeholder::_第几个参数)来按照对应的位置调整。如下:

int Sub(int a, int b)
{
	return a - b;
}

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

	// 调整参数顺序
	function<int(int, int)> f2 = bind(Sub, placeholders::_2, placeholders::_1);
	cout << f2(10, 5) << endl;

	// 调整参数个数,有些参数可以bind时写死
	function<int(int)> f3 = bind(Sub, 20, placeholders::_1);
	cout << f3(5) << endl;

	return 0;
}

用bind调整来包装成员函数

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<double(Plus*, double, double)> f2 = &Plus::plusd;
	Plus ps;
	cout << f2(&ps, 1.1, 2.2) << endl;

	function<double(Plus, double, double)> f3 = &Plus::plusd;
	cout << f3(Plus(), 1.11, 2.22) << endl;

//用bind来写死Plus()从而简化代码
	function<double(double, double)> f4 = bind(&Plus::plusd, Plus(), placeholders::_1, placeholders::_2);
	cout << f4(1.11, 2.22) << endl;

	return 0;
}


????????????????感谢你耐心的看到这里?( ′・?・` )比心,如有哪里有错误请踢一脚作者o(╥﹏╥)o!

????????????????????????????????????????????????????????????????给个三连再走嘛~

文章来源:https://blog.csdn.net/weixin_64038246/article/details/135322448
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。