行则至 發表於 2026-1-7 01:14:00

【C++】回调函数

<h2 id="前言">前言</h2>
<p>学习回调函数,<strong>回调函数</strong>是通过函数指针或对象调用的函数。</p>
<p>回调函数就是通过函数指针或对象调用的函数,只要能一个函数能够作为参数传入并调用,这个函数就是回调函数。</p>
<pre><code class="language-C++">#include &lt;iostream&gt;

int addCallBack(int a,int b){//回调函数
      std::cout &lt;&lt;a+b&lt;&lt;std::endl;
      return 0;
}

int main(int argc, char** argv) {

      int(*p)(int,int);
      p = addCallBack;
      p(1,2);
      return 0;
}
</code></pre>
<h2 id="为什么使用回调函数">为什么使用回调函数</h2>
<p>前言里直接在main函数调用addCallBack不是更直接吗?为什么要使用函数指针接收addCallBack的地址,再调用呢?</p>
<p>回调函数,通常是为了实现“控制反转”(Inversion of Control), 灵活、分离、 异步与并发。</p>
<ul>
<li>解耦和模块化: 函数与具体的逻辑解耦,可以复用。</li>
</ul>
<pre><code>// 排序算法(不关心具体比较逻辑)
void sort(int* arr, int n, bool(*compare)(int, int)) {
    for (int i = 0; i &lt; n-1; i++) {//解耦和模块化
      for (int j = i+1; j &lt; n; j++) {
            if (compare(arr, arr)) {
                std::swap(arr, arr);
            }
      }
    }
}

// 不同的比较策略
bool ascending(int a, int b) { return a &gt; b; }
bool descending(int a, int b) { return a &lt; b; }

int main() {
    int data[] = {5, 2, 8, 1, 3};
   
    sort(data, 5, ascending);   // 升序
    sort(data, 5, descending);// 降序
   
    return 0;
}
</code></pre>
<ul>
<li>异步处理:我不知道什么时候能算完</li>
</ul>
<pre><code class="language-C++">#include &lt;thread&gt;
#include &lt;functional&gt;
#include &lt;iostream&gt;
// 模拟异步任务
void asyncTask(std::function&lt;void(int)&gt; callback) {
    std::thread(() {
      std::this_thread::sleep_for(std::chrono::seconds(2));
      int result = 42;// 模拟计算结果
      callback(result);// 完成后通过回调通知
    }).detach();
}

// 回调处理结果
void handleResult(int result) {
    std::cout &lt;&lt; "异步任务完成,结果: " &lt;&lt; result &lt;&lt; std::endl;
}

int main() {
    std::cout &lt;&lt; "开始异步任务..." &lt;&lt; std::endl;
    asyncTask(handleResult);// 非阻塞调用

    // 主线程可以继续做其他事情
    for (int i = 0; i &lt; 5; i++) {
      std::cout &lt;&lt; "主线程工作..." &lt;&lt; i &lt;&lt; std::endl;
      std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    return 0;
}

</code></pre>
<h2 id="实现">实现</h2>
<h3 id="函数指针实现">函数指针实现</h3>
<h4 id="普通函数调用">普通函数调用</h4>
<pre><code class="language-C++">#include &lt;iostream&gt;

//回调函数 无参
void callBack(){
    std::cout&lt;&lt;"无参回调函数"&lt;&lt;std::endl;
}

//回调函数 带参数
void callback_ii(int a,int b){
    std::cout&lt;&lt;a+b&lt;&lt;std::endl;
}

//回调函数带返回值
int callback_return_i(){
      int a = 10;
      return a;
}

/*
定义函数指针
*/
//无参 函数指针
typedef void(*CallbackPtr)();

// 它是"指向返回void,接受两个int参数的函数"的指针类型
typedef void (*CallbackPtr_ii)(int, int);
// using CallbackPtr_using = void(*)(int, int);

//带返回值 函数指针
typedef int(*CallbackPtr_return_i)();

void performTask(CallbackPtr cb) {
    cb(); // 执行回调
}

void performTask_ii(int a, int b, CallbackPtr_ii cb) {
    // 业务逻辑...
    cb(a, b); // 执行回调
}

void performTask_return_i(CallbackPtr_return_i cb) {
    // 业务逻辑...
    std::cout&lt;&lt; cb() &lt;&lt;std::endl;
}

int main(){
    performTask(callBack);
    performTask_ii(1,2,callback_ii);
    performTask_return_i(callback_return_i);
    return 0;
}
   
</code></pre>
<p>这里其实就是使用指针调用函数。</p>
<blockquote>
<p>void (*p)(int ,int);</p>
<p>p = callback;</p>
<p>//p = &amp;callback;</p>
<p>(*p)(0,1);</p>
<p>//p(0,1);</p>
</blockquote>
<h4 id="类成员函数和类静态函数调用">类成员函数和类静态函数调用</h4>
<pre><code class="language-C++">#include &lt;iostream&gt;

class MyClass {
public:
    void Func(){
      std::cout &lt;&lt; "function" &lt;&lt; std::endl;
    }
    static void staticFunc() {
      std::cout &lt;&lt; "Static function" &lt;&lt; std::endl;
    }
};

int main() {
    void (*staticFuncPtr)() = &amp;MyClass::staticFunc;
    staticFuncPtr();// 输出: Static function
   /*
    void (*funcPtr)() =&amp;MyClass::Func;//error: cannot convert ‘void (MyClass::*)()’ to ‘void (*)()’ in initialization
    funcPtr();
    */
   // 指向普通成员函数 - 需要特殊的语法
    MyClass MyObj;
    void (MyClass::*FuncPtr)() = &amp;MyClass::Func;// 声明成员函数指针
    (MyObj.*FuncPtr)();// 通过对象调用,输出: function
   
    return 0;
}
</code></pre>
<h4 id="class-a-调用-class-b">Class A 调用 Class B</h4>
<pre><code class="language-C++">#include &lt;iostream&gt;

class ProgramA {
public:
void Func(void (*callback)()) {
    std::cout &lt;&lt; "A: callback" &lt;&lt; std::endl;
    callback();
}
};

class ProgramB {
public:
void Func() {
      std::cout &lt;&lt; "B: function" &lt;&lt; std::endl;
}
static void staticFunc() {
      std::cout &lt;&lt; "B: Static function" &lt;&lt; std::endl;
}
};

int main() {
ProgramA PA;
PA.Func(ProgramB::staticFunc);
return 0;
}
</code></pre>
<ul>
<li>如何使用A调用B中的非静态方法?</li>
</ul>
<p>这里只写两种方式。</p>
<p>方式一:使用function修改A的调用函数。</p>
<p>方式二:在A中修改参数</p>
<pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;functional&gt;

class ProgramB;

class ProgramA {
public:
//方式一
void Func(std::function&lt;void()&gt; callback) {
    std::cout &lt;&lt; "A std::function&lt;void(): callback" &lt;&lt; std::endl;
    callback();
}
//方式二
void Func(void(ProgramB::*callback)(),void *PBPtr){
      std::cout &lt;&lt; "A void(ProgramB::*callback)(): callback" &lt;&lt; std::endl;
      ((ProgramB*)PBPtr-&gt;*callback)();//*不是解引用,而是指针到成员运算符 -&gt;* 的一部分
}
};

class ProgramB {
public:
void Func() {
      std::cout &lt;&lt; "B: function" &lt;&lt; std::endl;
}
static void staticFunc() {
      std::cout &lt;&lt; "B: Static function" &lt;&lt; std::endl;
}
};

int main() {
ProgramA PA;
ProgramB PB;
PA.Func(ProgramB::staticFunc);

PA.Func([&amp;PB](){
      PB.Func();
      });

PA.Func(&amp;ProgramB::Func,&amp;PB);

return 0;
}

</code></pre>
<h3 id="lambda表达式实现">Lambda表达式实现</h3>
<ul>
<li>Lambda表达式语法</li>
</ul>
<pre><code class="language-C++">[捕获列表](参数列表) mutable exception -&gt; 返回类型 { 函数体 }
</code></pre>
<pre><code>void run(std::function&lt;void()&gt; cb) { cb(); }

int main() {
    int secret = 42;
    // 使用 Lambda 作为回调,并捕获局部变量 secret
    run(() {
      std::cout &lt;&lt; "数字是: " &lt;&lt; secret &lt;&lt; std::endl;
    });
}
</code></pre>
<h3 id="stdfunction-与-stdbind">std::function 与 std::bind</h3>
<p>C++11 引入的 <code>std::function</code> 是一个<strong>通用函数包装器</strong>。它可以存储、复制和调用任何“可调用对象”(函数指针、仿函数、Lambda、类成员函数</p>
<p>上面已经有关于function的内容,这里总结一下,</p>
<pre><code class="language-C++">#include &lt;iostream&gt;
#include &lt;functional&gt;

class Program {
public:
    void func(int status) {
      std::cout &lt;&lt; "func: " &lt;&lt; status &lt;&lt; std::endl;
    }
    static void staticFunc(){
      std::cout &lt;&lt; "staticFunc" &lt;&lt; std::endl;
    }
};

void gfunc(){
    std::cout &lt;&lt; "gfunc" &lt;&lt; std::endl;
}

int main() {
   
    //1, 类非静态函数
    Program d;
    // 绑定对象 d 到成员函数 onFinished
    std::function&lt;void(int)&gt; cb_1 = std::bind(&amp;Program::func, &amp;d, std::placeholders::_1);
    //std::placeholders::_1 这是一个占位符。
        //由于 func(int status) 需要一个整数参数,但我们在绑定时还不知道这个参数的具体值(它要在未来触发回调时才由调用者传入)。
        //_1 表示:这个位置的参数,请在未来调用 cb(value) 时,把第一个参数填到这里。
    cb_1(200);
   
    //2.类静态函数
    std::function&lt;void()&gt; cb_2 = Program::staticFunc;
    cb_2();
   
    //3 普通函数
    std::function&lt;void()&gt; cb_3 = gfunc;
    cb_3();
   
    //
    std::function&lt;void()&gt; cb_4 = &amp;gfunc;
    cb_4();
}
</code></pre><br><br>
来源:https://www.cnblogs.com/hjk-airl/p/18946018
頁: [1]
查看完整版本: 【C++】回调函数