函数指针与function以及bind用法

        函数指针顾名思义是指向的函数的指针。和其他指针类型一样,函数指针指向某种特定类型(特定参数和返回值)

        C/C++中定义函数指针:

        普通函数指针定义: typedef 返回值类型(*函数指针类型名)(参数列表)

         类成员函数指针定义: typedef 返回值类型(类名::*函数指针类型名)(参数列表)

        

typedef int(*FuncPtr)(int, int); // 定义函数指针 FuncPtr是定义的函数指针的类型
//如果函数指针指向类成员函数 typedef int(ClassName::*FuncPtr)(int, int); 

(*FuncPtr)(1,2);调用函数;

 函数类型是什么,通俗说就是参数和返回值一样的函数既函数类型相同,不管函数名是啥。

定义函数类型:

 typedef 返回值类型(函数类型名)(参数列表)

typedef int FuncType(int, int);	// 定义函数类型 函数类型参数和返回值一样的函数函数类型相同

用例:

#include 
#include 

int func1(int a, int b) {
	std::cout << "a: " << a << " b: " << b << std::endl;
	return a + b;
}

typedef int FuncType(int, int);	
typedef int(*FuncPtr)(int, int); 


int calFunc1(int a, int b, FuncType f)//函数类型可以作为形参类型使用
{
	return f(a, b);
}



int main()
{
	calFunc1(10, 1, func1);
	//FuncType f = func1;	//错误函数类型不能直接作为变量类型用
	FuncPtr pf = &func1;	//函数指针可以 &取函数地址传给函数指针
	(*pf)(100, 1);//调用函数func1


	return 0;
}



        C/C++引入了boost中的std::function,来实现类似函数指针功能,但是比函数指针更灵活,与bind配合使用效果极佳。

        std::function 是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

        std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。std::bind将可调用对象与其参数一起进行绑定,绑定后的结果可以使用std::function保存。

#include 
#include 

int func1(int a, int b) {
	std::cout << "a: " << a << " b: " << b << std::endl;
	return a + b;
}


int calFunc1(int a, int b, FuncType f)//函数类型可以作为形参类型使用
{
	return f(a, b);
}



int main()
{

	//普通函数
	std::function  fun1 = func1;//可以接收普通函数
	fun1(1000, 1);

	// lambda表达式
	int x = 100;
	int y = 2;
	auto lam = [=, &y](int a, int b)->int {
		y += x;
		std::cout << "x: " << x << " y: " << y << std::endl;
		std::cout << "a: " << a << " b: " << b << std::endl;
		return a + b; 
	};

	std::function  fun2 = lam;//可以接收lambda表达式
	fun2(10000, 1);
	
	//函数对象类
	struct stAdd {
		int operator()(int a, int b) {
			std::cout << "a: " << a << " b: " << b << std::endl;
			return a + b;
		}
	};
	std::function  fun3 = stAdd();
	fun3(100000, 1);

	//配合bind使用
	std::function  fun5 = std::bind(func1, std::placeholders::_1, std::placeholders::_2);
	fun5(200, 2);

	//只bind部分参数,减少可调用对象传入的参数
	std::function  fun6 = std::bind(func1, std::placeholders::_1, 2);
	fun6(200);

	//绑定一个类的成员函数
	class addClass {
	public:
		addClass(int _data) :data(_data) {};
		int add(int a, int b){
			std::cout << "a: " << a << " b: " << b << std::endl;
			std::cout << "data" << data << std::endl;
			return a + b;
		}
		int data;
	};
	//&addClass::add,因为编译器不会将对象的成员函数隐式转换成函数指针 所以用&取地址
	//用对象成员函数指针时,必须要知道该指针属于哪个对象,第二参数传对象指针
	addClass obj(101);
	std::function fun7 = std::bind(&addClass::add, &obj, 300, std::placeholders::_1);
	fun7(3); // 303

	return 0;
}

//lamda表达式: [函数对象参数](操作符重载函数参数)mutable或exception->返回值类型{函数体}

//[]没有任何函数对象参数
//[var]表示值传递方式捕捉变量var
//[=]表示值传递方式捕捉所有父作用域的变量
//[&var]表示引用传递捕捉变量var
//[&]表示引用传递方式捕捉所有父作用域的变量(包括this)
//[this]表示值传递方式捕捉当前的this指针

//() 没有参数,此时这部分可以省略。参数可以通过按值(如: (a, b))和按引用 (如: (&a, &b)) 两种方式进行传递。

// mutable,按值传递函数对象参数时,可以修改传递进来的拷贝(注意是能修改拷贝,而不是值本身) exception 指定函数抛出的异常,如抛出整数类型的异常,可以使用 throw(int)。这部分可以省略。

// ->返回值类型 如果没有返回值可以省略

//{函数体}函数具体实现

        

你可能感兴趣的:(C++语言,c++,bind,c++11)