【C++】函数指针 ④ ( 函数指针做函数参数 | 使用函数指针间接调用函数 | 函数指针做参数 | 函数指针类型的本质 | 函数指针做参数意义 )

2023-11-14 09:46:59 浏览数 (1)

一、函数指针做函数参数

1、使用函数指针间接调用函数

在上一篇博客 【C 】函数指针 ③ ( 函数指针语法 | 函数名直接调用函数 | 定义函数指针变量 | 使用 typedef 定义函数类型 | 使用 typedef 定义函数指针类型 ) 中 , 最后一个示例 , 使用 typedef 定义函数指针类型 如下 :

代码语言:javascript复制
// int (int, int) 函数指针类型重命名为 pFun_add
// 该类型变量可以直接接收 函数名 ( 函数地址 )
typedef int (*pFun_add)(int, int);

通过该指针类型 , 可以 间接调用 add 函数 ;

代码语言:javascript复制
	// 定义函数指针类型变量
	pFun_add pFun = add;
	// 通过函数指针间接调用 add 函数
	pFun(7, 8);

如果将 函数指针变量 pFun_add pFun 作为参数 , 传递给函数 , 在函数内部可以调用其它函数 , 调用的函数可以动态指定 ;

2、函数指针做参数

定义了 如下 函数指针类型 pFun_add , 其类型为 int (*)(int, int) , 该指针指向一个 类型为 int (int, int) 的 函数 ;

代码语言:javascript复制
// int (int, int) 函数指针类型重命名为 pFun_add
// 该类型变量可以直接接收 函数名 ( 函数地址 )
typedef int (*pFun_add)(int, int);

定义函数 接收 pFun_add 类型的形参作为参数 , 该类型是 函数指针类型 , 也就是 函数接收一个 函数指针类型参数 , 在该函数中调用 函数指针 指向的 函数 ;

代码语言:javascript复制
// 传入函数指针, 使用传入的函数进行计算
int caculate(pFun_add fun, int x, int y) {
	printf("使用 fun 函数计算 x 和 y = %dn", fun(x, y));
	return fun(x, y);
}

定义 caculate 函数时 , 只定义了 在函数体内部 要调用 int (int, int) 类型的函数 , 具体是什么函数 , 需要在运行时 , 动态传入 ;

函数指针类型 的该用法 是框架的基础 , 将 函数执行逻辑 与 软件框架 进行解耦 ;

也就是 将 任务调用者 与 任务实现者 进行了隔离 , 解耦合 ;

下面的示例中 , 可以将 函数指针类型变量 pFun_add pFun = add 传入函数作为参数 , 也可以直接将 add 函数名 ( 函数地址 ) 作为 函数指针 参数 传递给函数 ;

代码语言:javascript复制
	// 定义函数指针类型变量
	pFun_add pFun = add;
	// 通过函数指针间接调用 add 函数
	pFun(7, 8);

	// 将 函数指针 作为参数传递到函数中
	caculate(pFun, 9, 10);

	// 可以直接将 函数名 ( 函数地址 ) 作为 函数指针 参数 
	// 传递给函数
	caculate(add, 11, 12);

3、函数指针类型的本质

函数指针类型 本质 : 提前对任务 格式 进行约定 ;

  • 函数参数类型 约定了 函数的 参与者 ;
  • 函数返回值类型 约定了 函数的 执行结果 ;

只要 将 子任务 按照 上述 " 函数指针类型 " 的约定 , 开发出 符合要求 的 函数 , 就可以将其作为一个 子任务 传递到 其它函数中执行 ;

4、函数指针做参数意义

函数指针做参数意义 :

  • 提高程序灵活性 : 通过使用函数指针作函数参数 , 这样可以 在 程序 运行时 动态地 设置 要调用的函数 , 提高了程序的灵活性 ;
  • 作为回调函数 : 函数指针 可以作为 回调函数 ; 先将 函数指针变量 作为 实参 传递给 其它函数 , 在 接收函数指针 的函数内部 , 满足某种条件时直接调用该函数指针 指向的 函数 , 这样实现了回调 ;
  • 解耦 任务调用 与 任务实现 : 厂商提供 任务实现 , 系统集成商 调用 厂商实现的任务 , 此时 系统集成商 只需要写好 软件框架 , 调用 厂商提供的 任务实现即可 ;
  • 更好的代码组织 : C 语言 中模拟面向对象用法 ; 可以将特定的 函数指针类型 定义为 结构体 的一部分 , 并使用该 结构体 来传递具有特定行为的对象的地址 ; 该操作有助于更好地组织代码 , 使代码更易于理解和维护 ;
  • 错误处理 : 使用函数指针 , 将错误处理函数作为参数传递给其他函数 , 在发生错误时立即调用适当的错误处理函数 , 无需返回到调用堆栈中的较高层次 ;

二、代码示例 - 函数指针做函数参数


代码示例 :

代码语言:javascript复制
#include "iostream"
using namespace std; 

// int (int, int) 函数指针类型重命名为 pFun_add
// 该类型变量可以直接接收 函数名 ( 函数地址 )
typedef int (*pFun_add)(int, int);

int add(int x, int y) {
	printf("x   y = %dn", x   y);
	return x   y;
}

// 传入函数指针, 使用传入的函数进行计算
int caculate(pFun_add fun, int x, int y) {
	printf("使用 fun 函数计算 x 和 y = %dn", fun(x, y));
	return fun(x, y);
}

int main() {

	// 定义函数指针类型变量
	pFun_add pFun = add;
	// 通过函数指针间接调用 add 函数
	pFun(7, 8);

	// 将 函数指针 作为参数传递到函数中
	caculate(pFun, 9, 10);

	// 可以直接将 函数名 ( 函数地址 ) 作为 函数指针 参数 
	// 传递给函数
	caculate(add, 11, 12);

	// 控制台暂停 , 按任意键继续向后执行
	system("pause");

	return 0;
}

执行结果 :

代码语言:javascript复制
x   y = 15
x   y = 19
使用 fun 函数计算 x 和 y = 19
x   y = 19
x   y = 23
使用 fun 函数计算 x 和 y = 23
x   y = 23
Press any key to continue . . .

0 人点赞