C++ 中的回调函数

本文详细解析回调函数的概念,通过三个实例展示了如何在不同场景下使用回调函数,并探讨了回调函数在类中的局限性及解决方案。文章还介绍了如何在非静态成员函数作为回调函数时,以及不将回调函数设为static时的处理方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于回调函数

回调函数在百度百科的讲解是这样的

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

      通俗的理解 就是 有两个函数A,B,在函数B中有指向A函数的指针,函数B可以通过A函数的指针来调用A函数。

下面分三种情况来讲回调函数

   

1  回调函数是全局函数

   这种情况比较简单了  直接看代码    

typedef void(*pFun)(int);
void fun1(int a)
{
	cout << a << endl;

}

void  fun2(pFun pf,int m)
{
	pf(m);
}


int main()
{
	pFun p;
	p = fun1;
	fun2(p, 10);
	return 0;
}
打印的结果是 10

程序第一句 定义了一个函数指针,该函数接收1个int行形参,返回值为空,在main函数中,第一句定义一个函数指针类型的p,p可以指向一个接收一个int类型的参数,返回值为空的函数,第二句把 fun1函数赋值给p,第三句把p做为参数传递给fun2,在fun2中就可以调用fun1了。

        在C++中 大多数情况我们用到的都是类,那么在类中 类的非静态成员函数可以可以作为回调函数呢  答案是不可以的 ,因为普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递this指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为什么C++类的多个实例可以共享成员函数却-有不同的数据成员。由于this指针的作用,使得将一个成员函数作为回调函数安装时就会因为隐含的this指针使得函数参数个数不匹配,从而导致回调函数调用失败,要解决这个问题有两种方法

       第一种  既然回调函数不能有this指针 那么我们可以 把回调函数声明为静态的  代码如下

         

#include "stdafx.h"
#include <iostream>
using namespace std;

typedef void(*pFun)(int);
class B
{
public:
	B()
	{
		pf = NULL;
	}
	void  Show(int s)
	{
		pf(s);
	}
	void SetPf(pFun back)
	{
		if (back == NULL)
			return;
		this->pf = back;
	}

private:
	pFun pf;//声明一个函数指针

};


class A
{
public:
	static void BackShow(int m)
	{
		cout << "回调函数被调用:" <<m<< endl;
	}

};


int main()
{
	B *b = new B();
	b->SetPf(A::BackShow);
	b->Show(10);
	return 0;
}
输出结果为: 回调函数被调用:10  

         我们把A的静态成员函数地址 传递给b的pf,然后调用b的pf自然就调用的A的BackSHow方法了 ,但是在实际应用中,回调函数在大部分情况是需要访问类成员变量或者成员函数做一些事情的,如果把回调函数设为static,这样就需要类的成员变量和成员方法都设置成static  ,不和实际情况,解决方法是在类的静态成员做为回调函数的时候,给该回调函数传递一个this指针 代码如下

<pre name="code" class="cpp">#include "stdafx.h"
#include <iostream>
using namespace std;

typedef void(*pFun)(void*,int);

class A
{
public:
	static void backcall(void* a, int m)
	{
		A *af = (A*)a;
		af->show(m);
	}
	void show(int m)
	{
		cout << "A中show函数被调用:" << m << endl;
	}

};


class B
{
public:
	B()
	{
		a = NULL;
		pf = NULL;
	}
	void  CalledA(int m)
	{
		pf(a, m);
	}
	void SetA(A *a)
	{
		this->a = a;
		
	}
	void SetPf(pFun pf)
	{
		this->pf = pf;
	}
private:
	A *a;
	pFun pf;

};

int main()
{
	A *a = new A();
	B *b = new B();
	b->SetA(a);
	b->SetPf(A::backcall);
	b->CalledA(10);
	delete a;
	delete b;
}


       在调用回调函数的时候,传递给他一个A的对象就可以了访问非静态成员或方法了 ,那么有时候 我们不想把回调函数设为static 怎么办呢,代码如下 

      

#include "stdafx.h"
#include <iostream>
using namespace std;
typedef void(*pFun)(int);
class A
{
public:
	friend void BackCall(int m)
	{
		cout << "友元函数被调用" << m << endl;
	}

};

void show(pFun f)
{
	f(10);
}


int main()
{
	show(BackCall);
}

       

    


       

<think>嗯,用户问的是C++回调函数有没有优先级。首先,我需要确认回调函数的概念。回调函数通常是函数指针、函数对象或者Lambda表达式,在特定事件发生时被调用。然后,优先级这个说法在C++标准里是否存在呢? 记得C++标准本身并没有直接定义回调函数的优先级。回调的执行顺序更多依赖于它们的注册顺序或者调用它们的代码逻辑。比如,在事件驱动的系统中,先注册的回调可能先被调用,但这取决于具体的实现方式。 不过,用户可能是在某些框架或者库中遇到回调优先级的问题。比如,像Node.js的某些库可能有优先级设置,或者在游戏引擎中处理事件时有不同优先级的回调。这时候需要具体看上下文环境。 另外,线程调度也可能影响回调的执行顺序,比如多线程环境下,操作系统调度可能导致不确定性。但这不是C++语言层面的特性,而是系统或库的行为。 所以,总结来说,C++本身不提供回调的优先级机制,但开发者可以通过设计模式,比如优先级队列,或者依赖第三方库来实现类似功能。需要根据具体情况来处理回调的执行顺序。</think>在C++标准中,**回调函数本身没有内置的优先级机制**,但具体实现可以通过以下方式控制执行顺序: ### 核心概念 1. **回调本质**:通过函数指针、`std::function`或虚函数实现的延迟调用机制 2. **默认特性**:遵循注册顺序调用(先进先出),除非特别设计 ### 优先级实现方式 ```cpp // 示例:带优先级的回调队列 struct CallbackTask { int priority; std::function<void()> func; bool operator<(const CallbackTask& other) const { return priority < other.priority; // 优先值大的先执行 } }; std::priority_queue<CallbackTask> callbackQueue; // 注册回调 callbackQueue.push({3, []{ /* 高优先级任务 */ }}); callbackQueue.push({1, []{ /* 低优先级任务 */ }}); // 执行回调 while (!callbackQueue.empty()) { auto task = callbackQueue.top(); task.func(); callbackQueue.pop(); } ``` ### 应用场景中的优先级控制 1. **事件驱动框架**(如游戏引擎): - UI事件 > 物理计算 > 渲染回调 2. **网络框架**: - 系统控制指令 > 用户数据回调 3. **实时系统**: - 硬件中断回调 > 普通任务回调 ### 注意事项 1. 多线程环境下需加锁保证线程安全 2. 避免优先级反转问题(高优先级任务被低优先级阻塞) 3. 推荐使用`std::function`+优先队列的组合实现 4. 异步回调要考虑任务调度器的设计 是否需要具体示例说明某种特定场景下的优先级实现方式?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值