本章主要内容:
一,函数指针
1.函数指针的概念
2.函数指针的初始化
3.函数指针调用函数
4.函数指针的类型别名
二,回调函数
1.回调函数的概念
2.回调函数的代码样例
3.使用回调函数的原因
三,参考阅读
一,函数指针
1.函数指针的概念
函数指针的定义方式:
return_type (*function_pointer_name)(list_of_parameter_types);
注意,函数指针名称外面一定要有圆括号,不然就成了定义一个返回值类型为int指针的函数,样例:
int (*fun_ptr)(float*, int); //返回值类型为int的函数指针fun_ptr
int *fun(float*, int); //返回值类型为int*的函数fun
2.函数指针的初始化
long get_max(const long* array, size_t size); //获得数组的最大值函数
long (*fun_ptr)(const long*, size_t){get_max}; //用函数名初始化的函数指针
方式二,使用auto关键字初始化函数指针。
auto fun_ptr = get_max;
auto* fun_ptr = get_max;
//以上两种方式的初始化效果是一样的,使用auto*来初始化
//可以强调fun_ptr是一个指针变量,使代码可读性更强
//也可以采用地址运算符&来显式获取函数地址
auto* fun_ptr = &get_max;
auto fun_ptr = &get_max;
方式二的初始化操作比较简单,一旦初始化完成,fun_ptr指向的函数的参数列表和返回值类型将是固定不变的。
3.函数指针调用函数
方式一,使用”(*function_pointer_name)”的方式调用,此方式向代码阅读者强调了使用的是函数指针。
long data[]{ 23, 19, 4, 50 };
long max_data = (*fun_ptr)(data, std::size(data));
方式二,和函数调用的方式类似,直接利用函数指针的名称来调用。
long data[]{ 23, 19, 4, 50 };
long max_data = fun_ptr(data, std::size(data));
完整C++代码实现:
#include <iostream>
using namespace std;
long get_max(const long* array, size_t size);
int main()
{
auto* fun_ptr = &get_max;
//auto fun_ptr = &get_max;
//long (*fun_ptr)(const long*, size_t){get_max};
long data[]{ 23, 19, 4, 50 };
//long max_data = fun_ptr(data, std::size(data));
long max_data = (*fun_ptr)(data, std::size(data));
std::cout << "The max data is: " << max_data << std::endl;
return 0;
}
long get_max(const long* array, size_t size)
{
long max = array[0];
int i = 0;
for (i = 0; i < size; i++)
{
if (max < array[i])
{
max = array[i];
}
}
return max;
}
运行结果:
The max data is: 50
4.函数指针的类型别名
基于using关键字,我们可以给函数指针声明一个类型别名。
类型别名使得函数指针被用作函数参数或者对象的成员变量时的代码量更少。
long (*fun_ptr)(const long*, size_t);
step.01: 去掉函数指针名称,只保留类型关键字。
long (*)(const long*, size_t);
step.02: 基于using关键字的现代语法,左侧是自定义的名称,即类型别名,右侧是函数指针的返回值类型和传参列表。
using Array_max=long (*)(const long*, size_t);
step.03: 用类型别名定义函数指针变量
Array_max fun_ptr;
完整C++代码实现:
#include <iostream>
using namespace std;
using Array_max = long (*)(const long*, size_t);
long get_max(const long* array, size_t size);
int main()
{
Array_max fun_ptr = &get_max;
long data[]{ 23, 19, 4, 50 };
long max_data = fun_ptr(data, std::size(data));
std::cout << "The max data is: " << max_data << std::endl;
return 0;
}
long get_max(const long* array, size_t size)
{
long max = array[0];
int i = 0;
for (i = 0; i < size; i++)
{
if (max < array[i])
{
max = array[i];
}
}
return max;
}
运行结果:
The max data is: 50
同理,也可以基于typedef关键字来声明函数指针的类型别名。
用法如下:
typedef long (*fun_ptr_type)(const long*, size_t);
long get_max(const long* array, size_t size);
//用类型别名来初始化函数指针
fun_ptr_type fun_ptr = &get_max;
完整C++代码实现:
#include <iostream>
using namespace std;
typedef long (*fun_ptr_type)(const long*, size_t);
long get_max(const long* array, size_t size);
int main()
{
fun_ptr_type fun_ptr = &get_max;
long data[]{ 23, 19, 4, 50 };
long max_data = fun_ptr(data, std::size(data));
std::cout << "The max data is: " << max_data << std::endl;
return 0;
}
long get_max(const long* array, size_t size)
{
long max = array[0];
int i = 0;
for (i = 0; i < size; i++)
{
if (max < array[i])
{
max = array[i];
}
}
return max;
}
运行结果:
The max data is: 50
二,回调函数
1.回调函数的概念

学习回调函数的时候,不能被回调(callback)这个字眼给吓到。
通俗地描述:
这里有三个函数:函数A,函数B,函数C。
回调过程:函数C调用函数B的时候,函数B有个形参是函数指针,函数C将函数A的地址作为参数传给了函数B
主函数:函数C
中间函数:函数B
底层函数:函数A
用伪代码表示:
function A{
...
}
function C{
auto* fun_ptr = &A; //函数指针初始化
auto res = B(*fun_ptr); //调用函数B,并将函数A的地址作为参数传入
}
用C语言来简易实现:
#include<stdio.h>
void A()
{
printf("I am function An");
}
void B(void (*ptr)())
{
(*ptr) (); // callback to A
}
int main()
{
void (*ptr)() = &A;
B(ptr);
return 0;
}
运行结果:
I am function A
2.回调函数的代码样例
#include <map>
#include <iostream>
typedef void (*Callback)();
std::map<int, Callback> callback_map;
void RegisterCallback(int event, Callback func)
{
callback_map[event] = func;
}
bool finished = false;
int GetNextEvent()
{
static int i = 0;
++i;
if (i == 5)
finished = true;
return i;
}
void EventProcessor()
{
while (!finished)
{
int event;
event = GetNextEvent();
std::map<int, Callback>::const_iterator it = callback_map.find(event);
if (it != callback_map.end())
{
auto func_addr = it->second;
Callback func = *func_addr;
if (func)
{
(*func)();
}
else
{
std::cout << "No callback foundn";
}
}
}
}
void Cat()
{
std::cout << "Catn";
}
void Dog()
{
std::cout << "Dogn";
}
void Bird()
{
std::cout << "Birdn";
}
int main()
{
RegisterCallback(1, Cat);
RegisterCallback(2, Dog);
RegisterCallback(3, Cat);
RegisterCallback(4, Bird);
RegisterCallback(5, Cat);
EventProcessor();
return 0;
}
运行结果:
Cat
Dog
Cat
Bird
Cat
3.使用回调函数的原因
回调函数在两个独立的类或函数之间建立了一种通信渠道,可以通过给主函数传递不同的参数来随时让中间函数调用不同的底层函数。回调函数在事件驱动机制和通信场景下使用起来很方便。
三,参考阅读
原文始发于微信公众号(程序员与背包客):C/C++开发基础——函数指针&回调函数
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/128594.html