【C++】C++回调函数基本用法(详细讲解)

简介: 【C++】C++回调函数基本用法(详细讲解)


👉博__主👈:米码收割机

👉技__能👈:C++/Python语言

👉公众号👈:测试开发自动化【获取源码+商业合作】

👉荣__誉👈:阿里云博客专家博主、51CTO技术博主

👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。



1. 什么是回调函数?

回调函数可以被简单地理解为:A函数作为参数传递给B函数,然后B函数在执行的某一时刻调用A函数。这里的A函数就是回调函数。


2. 为什么需要回调函数

回调提供了一种灵活的方式来扩展或自定义函数的行为,需要在某些特定的时刻执行特定的动作,但这些动作可能因情境而异。通过使用回调,可以允许其他代码决定何时以及如何响应。


3. 回调函数的应用场合

  1. 事件驱动编程:在图形用户界面(GUI)编程中,用户的每一个动作,如点击按钮、移动鼠标等,都可能会触发一个事件。这些事件常常通过回调函数来处理。例如,当用户点击一个按钮时,你可能希望执行一个特定的函数。
  2. 异步编程:在网络编程或者其他需要异步处理的场景中,当一个长时间的操作(如网络请求)完成时,你可能希望执行某个函数。这个函数可以通过回调来指定。
  3. 定时器:某些编程环境允许你设置定时器,当定时器到期时执行一个函数。这个函数就是通过回调来指定的。
  4. 自定义排序:例如,在C++中,std::sort函数允许你传入一个回调函数来自定义排序逻辑。
  5. 遍历:如在前一个回答中所示,当你遍历一个集合并希望对每个元素执行特定操作时,可以使用回调函数。
  6. 线程或任务的回调:当你启动一个线程或提交一个任务,你可能希望在它完成时得到通知。这可以通过将回调函数传递给线程或任务来实现。
  7. 中间件和钩子:在某些框架中,你可能希望在请求处理的不同阶段插入自定义逻辑,如日志记录、验证等。这通常通过回调函数或钩子实现。
  8. 错误处理:你可以为可能出错的操作提供一个回调函数,当操作失败时,这个回调函数会被调用,并传入关于错误的信息。
  9. 数据库查询:在数据库编程中,当查询完成并返回结果时,你可以通过回调函数来处理这些结果。
  10. 动画和游戏开发:例如,当动画的某一帧完成渲染时或者游戏中某个事件发生时,你可能希望执行特定的回调函数。

4.举例说明

假设你有一个函数forEach,这个函数的任务是遍历一个整数数组,并对每个元素执行某个操作。这个“某个操作”可以通过回调函数来定义。

#include <iostream>
// 定义回调函数的类型
typedef void (*CallbackFunction)(int);
// 遍历数组,并对每个元素调用回调函数
void forEach(int* array, int size, CallbackFunction callback) {
    for (int i = 0; i < size; i++) {
        callback(array[i]);
    }
}
// 一个简单的打印函数,用作回调
void printNumber(int num) {
    std::cout << "Number: " << num << std::endl;
}
int main() {
    int arr[] = {1, 2, 3, 4, 5};
    forEach(arr, 5, printNumber);  // 使用printNumber作为回调函数
    return 0;
}

代码说明

  1. 引入头文件
#include <iostream>

这行代码包含了iostream头文件,允许我们使用C++标准库中的输入输出功能,例如std::cout

  1. 定义回调函数的类型
typedef void (*CallbackFunction)(int);

这里,我们定义了一个新的数据类型CallbackFunction,它是指向一个函数的指针。这个函数接受一个int参数并返回void

  1. forEach函数定义
void forEach(int* array, int size, CallbackFunction callback) {
    for (int i = 0; i < size; i++) {
        callback(array[i]);
    }
}

这个forEach函数接受三个参数:

  • 一个整数数组array
  • 数组的大小size
  • 一个回调函数callback,它的类型为CallbackFunction

函数的功能是遍历数组,并对数组的每个元素调用回调函数callback

  1. 回调函数定义
void printNumber(int num) {
    std::cout << "Number: " << num << std::endl;
}

printNumber函数是定义的回调函数。它接受一个int参数,并将这个数字打印到控制台。

  1. main函数
int main() {
    int arr[] = {1, 2, 3, 4, 5};
    forEach(arr, 5, printNumber);  // 使用printNumber作为回调函数
    return 0;
}

main函数是程序的入口点。

首先,定义了一个包含5个整数的数组arr

然后,调用forEach函数,并将数组arr、其大小(5)以及回调函数printNumber作为参数传递给它。

forEach函数执行时,它会遍历数组的每个元素,并对每个元素调用printNumber函数。因此,输出将是:

Number: 1
Number: 2
Number: 3
Number: 4
Number: 5

这个例子演示了如何在C++中定义和使用回调函数。定义了一个forEach函数,它接受一个数组和一个回调函数作为参数,并对数组的每个元素调用回调函数。


5. 高级回调方式

在现代C++中,我们经常使用函数对象、lambda函数和std::function来实现更灵活的回调。

例如,使用lambda表达式:

#include <iostream>
#include <vector>
#include <functional>
void forEach(const std::vector<int>& numbers, const std::function<void(int)>& callback) {
    for (int num : numbers) {
        callback(num);
    }
}
int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    forEach(numbers, [](int num) {
        std::cout << "Number: " << num << std::endl;
    });
    return 0;
}


相关文章
|
3月前
|
编译器 C++ 容器
【C++】String常见函数用法
【C++】String常见函数用法
|
6月前
|
人工智能 机器人 测试技术
【C++】static_cast基本用法(详细讲解)
【C++】static_cast基本用法(详细讲解)
150 0
|
4月前
|
存储 C++ 运维
开发与运维函数问题之使用C++标准库中的std::function来简化回调函数的使用如何解决
开发与运维函数问题之使用C++标准库中的std::function来简化回调函数的使用如何解决
52 6
|
3月前
|
存储 程序员 编译器
c++学习笔记08 内存分区、new和delete的用法
C++内存管理的学习笔记08,介绍了内存分区的概念,包括代码区、全局区、堆区和栈区,以及如何在堆区使用`new`和`delete`进行内存分配和释放。
48 0
|
4月前
|
C++
C++ string中的函数和常用用法
C++ 中string中的函数和常用用法
42 4
|
5月前
|
存储 C++
C++初阶学习第十一弹——探索STL奥秘(六)——深度刨析list的用法和核心点
C++初阶学习第十一弹——探索STL奥秘(六)——深度刨析list的用法和核心点
53 7
|
5月前
|
存储 人工智能 C++
map容器在C++中的具体用法以及相关注意点
map容器在C++中的具体用法以及相关注意点
52 1
|
5月前
|
安全 API C++
逆向学习Windows篇:C++中多线程的使用和回调函数的实现
逆向学习Windows篇:C++中多线程的使用和回调函数的实现
183 0
|
6月前
|
编译器 C++
【C++】【C++的常变量取地址问题(对比C的不同)】const修饰的常变量&volatile修饰用法详解(代码演示)
【C++】【C++的常变量取地址问题(对比C的不同)】const修饰的常变量&volatile修饰用法详解(代码演示)
|
6月前
|
安全 程序员 C++
C++ new和delete的用法
需要注意的是,使用 `new`和 `delete`分配和释放内存时,程序员负责管理内存的分配和释放,这可能导致内存泄漏或释放已释放内存的问题。因此,C++引入了智能指针(如 `std::shared_ptr`和 `std::unique_ptr`)以更安全和自动化地管理内存。
99 2