当前位置: 首页 > news >正文

C++函数指针

函数指针的调用:

调用函数的两种方式:

  • 直接调用:通过函数名(函数的入口地址)直接调用
  • 间接调用:通过函数指针指向函数间接调用
void(*p_fun)(int)=&fun; //定义变量并初始化
p_fun = &fun; //赋值,指向一个函数
(*p_fun)(10); //间接调用函数
#include <iostream>
using namespace std;// 定义一个函数,接受一个整数参数并打印
void show(int a) {cout << "show(int)" << " " << a << endl;
}// 定义一个函数,接受一个函数指针作为参数
void fun_show(void (*p_fun)(int)) {(*p_fun)(30); // 通过函数指针调用传入的函数
}int main() {show(10); // 直接调用 show 函数,输出: show(int) 10// 定义一个函数指针并初始化,使其指向 show 函数void (*p_fun)(int) = &show; //定义函数指针且初始化,可以不加取地址符号,因为函数名就是函数地址(*p_fun)(20); // 可以用这行代码间接调用 show 函数,输出: show(int) 20// 直接调用函数指针 p_funp_fun(20); // 使用函数指针 p_fun 调用 show 函数,输出: show(int) 20// 将函数指针 p_fun 赋值为 show 函数(可以省略取址符号 &)p_fun = &show; // 赋值(&show 是可选的)// 调用 fun_show,并将函数指针 p_fun 作为参数传递fun_show(p_fun); // 输出: show(int) 30return 0;
}

函数指针有时看起来比较繁琐、可读性差一些,我们可以用typedef进行优化 

typedef void(*P_FUN)(int);
P_FUN p_fun = &fun;
//将函数指针用typedef进行优化
#include <iostream>
using namespace std;// 定义一个接受一个整数参数并打印的函数
void show(int a) {cout << "show(int)" << " " << a << endl;
}// 使用 typedef 优化函数指针的定义
typedef void (*P_FUN)(int);// 定义一个函数,接受一个函数指针作为参数
void fun_show(P_FUN p_fun) {(*p_fun)(30); // 通过函数指针调用传入的函数,并传入 30
}int main() {P_FUN p_fun = &show; // 使用 typedef 定义的函数指针并指向 show 函数fun_show(p_fun); // 调用 fun_show,并传入 p_funreturn 0;
}

使用函数指针调用函数的好处:

函数指针可以实现同一功能的多个模板统一标识起来,是系统结构清晰,后期更容易维护,便于分层设计,利于系统抽象,降低耦合,使接口与实现分离,提高代码的复用性,扩展性

嵌套函数指针:

#include <iostream>
using namespace std;/*
func :函数名 挨着函数名的第一个括号里是参数
参数列表:(char*, void(*)(bool, double*)) ,两个参数,参数1:char*
参数2:void(*)(bool, double*)
返回值:void (*)(int*, void* (char, bool*)),返回值是函数指针,指向的函
数:void (int*, void* (char, bool*))
*/// 定义函数指针类型
typedef void(*P_PARAM)(bool, double*); // P_PARAM 指向接受 bool 和 double* 的函数
typedef void* F_PARAM(char, bool*); // F_PARAM 指向接受 char 和 bool* 的函数并返回 void*
typedef void (*P_RET)(int*, F_PARAM f); // P_RET 指向接受 int* 和 F_PARAM 的函数// func 函数定义,接受 char* 和一个函数指针
void (*func(char*, void(*)(bool, double*)))(int*, void* (char, bool*)) {cout << "优化前函数" << endl;return nullptr; // 返回值应为 nullptr,表示没有返回有效指针
}// func1 函数定义,接受 char* 和 P_PARAM 类型函数指针
P_RET func1(char*, P_PARAM p1) {cout << "优化后函数" << endl;return nullptr; // 返回值应为 nullptr,表示没有返回有效指针
}int main() {char* p = new char[1](); // 动态分配一个字符数组P_PARAM p11 = nullptr; // 初始化函数指针 p11 为 nullptrP_RET pRet = func(p, p11); // 调用 func 函数pRet = func1(p, p11); // 调用 func1 函数delete[] p; // 释放之前分配的内存return 0;
}

类成员函数指针:

 类成员函数与普通的函数的区别:

  1. 所属的作用域不同,类成员函数标识了所属的类,必须通过对象调用(虽然可以是空指针对象,但必须得有)。
  2. 类成员函数编译器会默认加上一个隐藏的参数: this指针。所以定义类成员函数的指针与普通的函数指针肯定会有所区别:C++ 提供了三种运算符 ::* 、.*、 ->. 用于定义和使用类成员函数指针。
  3. 类成员函数指针的&取地址符号不可省略,而普通函数的可以。
::* :定义类成员函数指针
.* :用对象通过类成员函数指针调用指向的函数
->* :用指针对象通过类成员函数指针调用指向的函数
注:
类成员函数指针的定义一定是 void (CTest ::* p_fun)(int a) = &CTest::show;
而不是 void (CTest ::(*p_fun)(int a) = &CTest::show;

类成员函数定义与调用:

#include <iostream>
using namespace std;
class CTest {public:void show(/* CTest * const this */int a) {cout << this << endl; //输出tst的地址cout << "CFather::show" << a << endl;}
};
int main() {void (CTest::*p_fun)(int a) = &CTest::show;
//定义类成员函数指针并初始化,注意:& 和类名作用域 都不能省略,//优化typedef void (CTest::*P_FUN)(); //使用typedef 进行优化P_FUN p_fun2 = &CTest::show;//定义CTest tst;CTest*pTst = new CTest;CTest* pTst = &tst;//调用(pTst->*p_fun)(20);(tst.*p_fun2)(); //普通对象通过指针调用类成员函数(pTst->*p_fun2)(); //指针对象通过指针调用类成员函数}

仿写多态:

可以用类成员函数指针来模拟实现多态。用父类指针调用子类函数

 

#include <iostream>
using namespace std;
class CPeople {public:int m_money;CPeople() {m_money = 10;}void cost(int n) {m_money -= n;}void show() {cout << "m_money:" << m_money << endl;}
};
class CYellow :public CPeople {public:void eat() {cout << "用筷子夹菜吃饭" << endl;}
};
class CWhite :public CPeople {public:void eat() {cout << "用刀叉吃肉" << endl;}
};
class CBlack :public CPeople {public:void eat() {cout << "用手抓饭" << endl;}
};
typedef void(CPeople::* P_FUN)();
void fun(CPeople* p, P_FUN p_fun) {p->cost(1);p->show();(p->*p_fun)(); // 调用成员函数
}//CPeople* p,这是一个指向 CPeople 类对象的指针。//由于 CPeople 是一个基类,p 可以指向任何 //CPeople 的派生类对象(例如 CYellow、CWhite、CBlack),//这体现了多态性的特性。//P_FUN p_fun,这是一个指向 CPeople 类成员函数的指针。//P_FUN 是之前定义的类型别名,表示返回类型为 void,//且没有参数的成员函数指针。通过传递这个指针,//可以在 fun 函数内部调用特定的成员函数。int main() {CPeople* pPeo = new CYellow;typedef void(CPeople::* P_FUN)();
//void(CPeople:: * p_fun)() = (void(CPeople::*)())&CYellow::eat;P_FUN p_fun = (P_FUN)&CYellow::eat; // 获取 CYellow::eat 的指针
//通过强转指向子类的函数(pPeo->*p_fun)(); // 调用 eat 方法fun(new CWhite, (P_FUN)&CWhite::eat); // 调用 CWhite 的 eat 方法fun(new CBlack, (P_FUN)&CBlack::eat); // 调用 CBlack 的 eat 方法return 0;
}

http://www.dtcms.com/a/278445.html

相关文章:

  • Redis作缓存时存在的问题及其解决方案
  • 云原生核心技术解析:Docker vs Kubernetes vs Docker Compose
  • Word 与 Excel 下拉菜单对比(附示例下载)
  • 前端将传回的List数据组织成树形数据并展示
  • MEMS IMU如何赋能无人机与机器人精准感知?
  • 跨膜粘蛋白MUC17
  • MAC安装虚拟机
  • UE5多人MOBA+GAS 22、创建技能图标UI,实现显示蓝耗,冷却,以及数字显示的倒数计时还有雷达显示的倒数计时
  • IDEA中使用Servlet,tomcat输出中文乱码
  • ubuntu22.04下配置qt5.15.17开发环境
  • Kotlin委托
  • 【Python】基础语法
  • 亚马逊新规!7月13日起合规性文件须出自符合要求的实验室!
  • 【飞牛云fnOS】告别数据孤岛:飞牛云fnOS私人资料管家
  • 【Hadoop科普篇】大数据怎么处理?Hadoop是什么?跟HDFS, Spark, Flink, Hive, Hbase是什么关系?
  • 嵌入式硬件篇---晶体管的分类
  • 大数据系列之:通过trino查询hive表
  • [Nagios Core] struct监控对象 | 配置.cfg加载为内存模型
  • Kotlin集合接口
  • HTTP 四种常见方法
  • 基于Hadoop的竞赛网站日志数据分析与可视化(上)
  • 基于hadoop的竞赛网站日志数据分析与可视化(下)
  • 神经网络与深度学习Python入门
  • 构建高效事件驱动架构:AWS S3与SQS集成实践指南
  • 实战:如何创建 AWS RDS 数据库
  • 显示器核心三要素详解:刷新率、分辨率、色深
  • 【JAVA】监听windows中鼠标侧面键的按钮按下事件
  • Web 前端面试
  • redis实现红锁
  • (1-7-3)数据库的基本查询