C++学习笔记-回调函数,函数指针,指针函数,递归函数

回调函数,函数指针,指针函数,递归函数

  • 回调函数,函数指针,指针函数
      • 1.函数指针
          • 指针函数和函数指针的区别:
      • 2.回调函数
        • 怎么理解
        • 什么时候用
        • 怎么用
        • 什么时候执行
        • 什么好处
        • 同步回调函数和异步回调函数
  • 递归函数
    • 用法

回调函数,函数指针,指针函数

1.函数指针

是指向函数的指针变量。 因此“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。

指针函数和函数指针的区别:

1,指针函数是指返回值是指针的函数,即本质是一个函数。我们知道函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。
2,函数指针的本质是一个指针,该指针的地址指向了一个函数,所以它是指向函数的指针。我们知道,函数的定义是存在于代码段,因此,每个函数在代码段中,也有着自己的入口地址,函数指针就是指向代码段中函数入口地址的指针。
事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。

int PtrFuction()
{
	cout << "PtrFuction---------------";
	return 100;
}
int PtrFuction_2(int x ,int y)
{
	cout << "PtrFuction_2---------------";
	return x*y;
}
	cout << (PtrFuction) << endl;
	cout<< (*PtrFuction)<<endl;
	cout << (&PtrFuction)<<endl;
	cout << (PtrFuction)() << endl;
	cout << (*PtrFuction)() << endl;
	cout << (&PtrFuction)() << endl;
		//000000013F891D4D
		//000000013F891D4D
		//000000013F891D4D
		//PtrFuction-------------- - 100
		//PtrFuction-------------- - 100
		//PtrFuction-------------- - 100

甚至可以用数组存放

	int(*Array[])(void) = { PtrFuction,PtrFuction,PtrFuction };
	cout << Array[1]<<"    " << Array[1]() << endl;

	vector<int(*)()> Array2(5, PtrFuction);
	cout << Array2[1]<<"    "<< Array2[1]() << endl;

2.回调函数

通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

怎么理解

假设A随机的是个时间会给B发一个数据,但是不知道是什么时候,这时候有两个方案
1,B每隔一段时间去查找是否获得这个数据,主动权在B。
2,A在发信息的时候调用B,主动权在A。
因为不知道A什么时候发数据,所以方法一不可行。

什么时候用

当需要执行一个任务而,但是不确切是什么时候

怎么用

把需要的事件封装成函数,再把这个函数和某一时间或者事件,中断建立关联。

什么时候执行

当需要的时候,回调函数会被执行。

什么好处

不需要等到需要调用这个函数的时候在调用它。

int PtrFuction_2(int x ,int y)
{
	cout << "PtrFuction---------------" << endl;
	return x*y;
}
typedef int(*PtrFun)(int,int);     //定义一个函数指针类型 

void CallPtr(PtrFun PtrFuction_2,int x = 1,int y = 1)
{
	cout << "执行回调函数---------------" << endl;
	int Ans = PtrFuction_2(x, y);
	cout << "结束回调函数---------------" << endl;
}
	CallPtr(PtrFuction_2);
	CallPtr(PtrFuction_2,3);
	CallPtr(PtrFuction_2,3,2);
	//同步的执行

同步回调函数和异步回调函数

1,回调可以是同步也可以是异步
2,同步可以是单线程也可以是多线程
3, 异步必须是多线程或多进程(每个进程可以是单线程) ,异步必须依靠多线程或多进程才能完成。
同步毁掉:A要等B执行完才能继续。
异步回调:A不需要等B,A继续执行,B独自执行。

异步调用:

#include 
#include
#include
#include
using namespace std;
typedef void(*PtrCallBack)(int x);

struct Parameter
{
	int i;
	PtrCallBack CallBck;//函数指针

	Parameter(int i, PtrCallBack CallBck) :i(i), CallBck(CallBck) {};
};
void CallBack_thread(Parameter* p)
{
	Parameter* p1 = (Parameter*)p;
	Sleep(600);
	p1->CallBck(p1->i);//执行B
}
void SetCallBack(int i, PtrCallBack CallBck)
{
	cout << "A开始了" << endl;
	Parameter* p = new Parameter(i, CallBck);

	thread th(CallBack_thread,p);
	
	
	cout << "A结束了" << endl;
	th.detach();
}

void CallBck(int i)
{
	cout << "B开始了" << endl;
	cout << i << endl;
	Sleep(600);
	cout << "B结束了" << endl;
}


int main()
{
	SetCallBack(456, CallBck);
}

递归函数

函数直接或间接调用函数本身,则该函数称为递归函数。递归函数不能定义为内联函数。

用法

如下,这是LeetCode上一道简单难度的镜像二叉树的题目,可以看到isSymmetric(TreeNode* root)一直再调用自身。
递归的底层实现其实是一个栈。栈的特点是**后进先出,**也就是最后进入栈的事件是最先被处理的,递归到最内层(到退出条件),开始从内层向外逐层调用函数自己计算处理。
优点:使用递归时,常常可以让代码更加简洁
缺点:递归会占用比较多的内存,当递归次数比较多时,性能就会降低

struct TreeNode {
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
	bool isSymmetric(TreeNode* root) {
		return IsSame(root, root);
	}

	bool IsSame(TreeNode* l1, TreeNode* l2)
	{
		if (l1 == nullptr && l2 == nullptr)
		{
			return true;
		}
		if (l1 == nullptr || l2 == nullptr)
		{
			return false;
		}
		return (l1->val == l2->val) 
			&& IsSame(l1->right, l2->left) 
			&& IsSame(l1->left, l2->right);
	}
};

你可能感兴趣的:(回调函数,函数指针)