• C++语法基础:函数指针


    前言

            "打牢基础,万事不愁" .C++的基础语法的学习."学以致用,边学边用",编程是实践性很强的技术,在运用中理解,总结.

    引入 

            指针的一种,前一篇和指针相关的帖子C++基础语法:指针“进阶“---结点,双重指针-CSDN博客 

     函数指针的思想

            既然属于指针的一种,他背后的设计思想也是指针的思想.

            回顾指针

            1>指针的值是内存地址,除了将指针值映射到硬件地址,其他情况下一般不关注指针的值

             2>指针可以间接访问数据. 指针用于指向单个数据或者数据集合(数组或结点),指针一般指向数据集合,实现对集合元素的访问;指向单个数据时,多半用于需要修改传入的数据. 

            3>双重指针多用于指向指针数组.

    函数指针的定义

            首先,回顾函数的形式:

                    返回值类型  函数名(形参类型 形参) 

            每个函数的特征:返回值类型形参类型,这两样决定了函数的类型.

            定义格式: typedef + 返回值类型+ (*函数指针名)+(形参类型,形参名)

    举例

    1. #include<iostream>
    2. typedef int (*pfi)(int i,int j); //函数指针声明,定义新类型
    3. int add(int i, int j); //整数加法定义
    4. int add(int i, int j, int k); //重载整数加法
    5. int sub(int i, int j); //整数减法定义
    6. int apply(pfi pf, int i, int j); //函数指针作为参数,可调用加法或者减法
    7. int main(void) {
    8. pfi pa = add; //函数指针变量指向指针常量(函数名)
    9. pfi ps = sub; //函数指针变量指向指针常量(函数名)
    10. int result_add = apply(add, 1, 2); //传入函数名add,调用加法函数
    11. std::cout <<"传入函数名得到的加法结果是:" << result_add << std::endl;
    12. int result_adds = apply(pa, 1, 2); //传入函数指针变量,调用加法函数
    13. std::cout <<"传入函数指针得到的加法结果是:" << result_add << std::endl;
    14. int result_sub = apply(sub, 1, 2); //传入函数名sub,调用减法函数
    15. std::cout << "传入函数名得到的减法结果是:" << result_sub << std::endl;
    16. //以下报错,函数指针不能用于重载
    17. // int result_add = apply(add, 1, 2,3); //传入函数名add,调用加法函数
    18. }
    19. int add(int i, int j) {
    20. return i + j;
    21. }int sub(int i, int j) {
    22. return i - j;
    23. }
    24. int apply(pfi pf, int i, int j) {
    25. int tmp=(*pf)(i, j); //pf是指向pfi类型的函数指针,*pf表示函数
    26. return tmp;
    27. }
    28. int add(int i, int j,int k) { //函数指针不能指向重载函数
    29. return i + j+k;
    30. }

    说明:  用一个其他的例子来比较,传入函数名相当于传入字面常量; 

    1. int a=3;
    2. int *p=&a;
    3. show(3); //相当于调用apply(add, 1, 2)
    4. show(*a); //相当于调用apply(pa, 1, 2)
    5. void show(int i){
    6. std::cout<<"你输入的数字是:"<<i<<endl;
    7. }

            相信看了这个例子,也不知道函数指针到底能干什么,直接用函数名调用函数不就行了吗?说实话,我也不知道函数指针的用途在哪里,估计暂时没找到适用场景.但既然设计出来总会有他的道理.

            函数名是函数指针所指向的常量   

    其他

            <> 6th Edition上有个例子,指向函数指针的数组的指针,大意如下:

    1. pfi par[] = { pa,ps }; //建立函数指针数组
    2. pfi* ppar = par; //建立指向函数指针数组的指针
    3. pfi par1[] = { add,sub }; //建立函数指针数组
    4. pfi* ppar1 = par1; //建立指向函数指针数组的指针

            无论数组元素是什么类型,要建立指向数组的指针,都可以遵循这个基本思路:

             数组元素类型+*  指针变量名=数组名

             这里的数组元素是函数指针类型的元素,可以用函数名或者已赋值的指针变量

            此外另一本书上讲了一个例子,把一个类的所有方法调出来用一遍,或许是函数指针真正的应用

    更新

            函数指针做参数的函数,比没有函数指针做参数的函数,有利于多段逻辑的表达.程序有多个函数调用组成.每个函数代表了一段逻辑.例如

    1. //伪代码
    2. int fun1(int a); //函数1
    3. int fun2(int a); //函数2
    4. typedef int (*pf)(int a); //函数指针,指向函数1和函数2;

             如果我现在要写个函数,当调用fun1(n)或者fun2(n)时大于某个值返回true,否则返回false

    1. //伪代码
    2. bool is_big(int compare_value,int para_value){ //fun1()的比较
    3. if(fun1(para_value)>compare_value)
    4. return true;
    5. return false;
    6. }
    7. bool is_bigg(int compare_value,int para_value){ //fun2()的比较
    8. if(fun2(para_value)>compare_value)
    9. return true;
    10. return false;
    11. }
    12. =======================
    13. is_big(100,10); //比较100和fun1(10)的大小
    14. is_bigg(100,10); //比较100和fun2(10)的大小

            现在用函数指针来写

    1. //伪代码
    2. bool is_big(int compare_value,int para_value,pf pff){ //函数指针做参数
    3. if((*pff)(para_value)>compare_value)
    4. return true;
    5. return false;
    6. }
    7. =========================
    8. is_big(100,10,fun1); //比较100和fun1(10)的大小
    9. is_big(100,10,fun2); //比较100和fun2(10)的大小

            感觉好很多,一是函数命名不用想,二是代码量少了.

  • 相关阅读:
    Kafka3.x核心速查手册二、客户端使用篇-4、消息路由机制
    使用Dokcer中的Mysql导入sql文件
    (附源码)ssm高校运动会管理系统 毕业设计 020419
    BUUCTF-----[CISCN 2019 初赛]Love Math
    Java 泛型
    【力扣刷题】Day09——字符串专题
    riscv引导程序及仿真记录
    计算机编码与解码&编码表
    深度学习参数初始化(一)Xavier初始化 含代码
    从头学前端-HTML简介
  • 原文地址:https://blog.csdn.net/jllws1/article/details/139836890