函数指针(Function Pointer)与 typedef int (*FuncPtr)(int, int);typedef与using(更推荐)
C++ 函数指针(Function Pointer)详解
函数指针是指向函数的指针,它可以存储函数地址,并通过该指针调用函数。函数指针在回调函数、策略模式、动态函数调用等场景中非常有用。
1. 什么是函数指针?
函数指针是一个指向函数的指针,它存储的是函数的地址,并允许通过指针调用该函数。
📌 语法
返回类型 (*函数指针名)(参数列表);
2. 基本示例
(1)定义和使用函数指针
#include <iostream>// 普通函数
void hello() {std::cout << "Hello, Function Pointer!" << std::endl;
}int main() {void (*funcPtr)(); // ✅ 定义函数指针funcPtr = hello; // ✅ 让指针指向 `hello` 函数funcPtr(); // ✅ 通过指针调用函数return 0;
}
📌 输出
Hello, Function Pointer!
✅ funcPtr 存储 hello 函数地址,并通过 funcPtr() 调用它。
3. 带参数和返回值的函数指针
#include <iostream>// 带参数和返回值的函数
int add(int a, int b) {return a + b;
}int main() {int (*funcPtr)(int, int); // ✅ 定义函数指针funcPtr = add; // ✅ 让指针指向 `add`std::cout << funcPtr(3, 5) << std::endl; // ✅ 通过指针调用 `add(3, 5)`return 0;
}
📌 输出
8
✅ funcPtr 存储 add() 地址,调用 funcPtr(3, 5) 计算 3 + 5。
4. 函数指针作为函数参数
函数指针可以作为回调函数,在函数内部调用:
#include <iostream>// 定义回调函数类型
void process(int a, int b, int (*op)(int, int)) {std::cout << "Result: " << op(a, b) << std::endl;
}// 具体实现
int add(int x, int y) { return x + y; }
int multiply(int x, int y) { return x * y; }int main() {process(3, 5, add); // ✅ 传递 `add` 函数process(3, 5, multiply); // ✅ 传递 `multiply` 函数return 0;
}
📌 输出
Result: 8
Result: 15
✅ process(3, 5, add) 让 op 绑定到 add(),支持动态调用!
5. 使用 typedef 或 using 简化函数指针
函数指针的语法比较复杂,可以使用 typedef 或 using 来简化。
(1)使用 typedef
typedef int (*FuncPtr)(int, int); // ✅ 定义函数指针类型int subtract(int a, int b) { return a - b; }int main() {FuncPtr ptr = subtract; // ✅ 使用 `FuncPtr`std::cout << ptr(10, 3) << std::endl;
}
(2)使用 using(C++11)
using FuncPtr = int (*)(int, int); // ✅ 定义函数指针类型(C++11)int subtract(int a, int b) { return a - b; }int main() {FuncPtr ptr = subtract; // ✅ 使用 `FuncPtr`std::cout << ptr(10, 3) << std::endl;
}
✅ typedef 和 using 让代码更简洁!
6. 函数指针数组
函数指针可以组成数组,实现动态选择函数:
#include <iostream>int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }int main() {int (*operations[3])(int, int) = { add, subtract, multiply }; // ✅ 函数指针数组std::cout << operations[0](3, 4) << std::endl; // 3 + 4 = 7std::cout << operations[1](7, 2) << std::endl; // 7 - 2 = 5std::cout << operations[2](3, 3) << std::endl; // 3 * 3 = 9
}
📌 输出
7
5
9
✅ 使用索引动态调用不同函数,提高灵活性!
7. C++11 std::function(更现代的方式)
C++11 提供了 std::function 作为函数指针的现代替代,它支持Lambda 表达式、成员函数、绑定参数等:
#include <iostream>
#include <functional> // ✅ 引入 `std::function`int add(int a, int b) { return a + b; }int main() {std::function<int(int, int)> func = add; // ✅ 绑定普通函数std::cout << func(3, 5) << std::endl; // ✅ 运行
}
✅ std::function 允许存储更复杂的调用目标,如 Lambda 和成员函数!
8. 结论
| 功能 | 函数指针 | **std::function(C++11+) |
|---|---|---|
| 存储普通函数 | ✅ 支持 | ✅ 支持 |
| 存储 Lambda | ❌ 不支持 | ✅ 支持 |
| 存储成员函数 | ❌ 复杂 | ✅ 方便 |
| 类型安全 | ❌ 可能出错 | ✅ 更安全 |
| 适用场景 | 轻量级回调 | 泛型函数封装 |
🚀 推荐:C++11 及以上,使用 std::function 代替传统函数指针! 🚀
是的,typedef 在 C++ 中的作用是 给已有类型取别名,但在函数指针的场景中,它可以让复杂的函数指针声明变得更易读和使用。
1. 为什么 typedef 可以用于函数指针?
函数指针的标准声明可能会很复杂,例如:
int (*funcPtr)(int, int);
这意味着 funcPtr 是一个指针,指向一个接受两个 int 参数并返回 int 的函数。
如果我们要在多个地方使用这个函数指针类型,每次都要写 int (*)(int, int),这既冗长又容易出错。使用 typedef 让它更清晰:
typedef int (*FuncPtr)(int, int);
这表示:
FuncPtr是一个新的类型别名,它等价于int (*)(int, int)。- 现在,我们可以直接使用
FuncPtr来定义函数指针:FuncPtr ptr; // 等价于 int (*ptr)(int, int);
2. typedef 在函数指针中的使用
✅ 使用 typedef 简化函数指针
#include <iostream>typedef int (*FuncPtr)(int, int); // ✅ 定义函数指针类型别名int add(int a, int b) { return a + b; }int main() {FuncPtr ptr = add; // ✅ `ptr` 现在是一个函数指针std::cout << ptr(3, 5) << std::endl; // ✅ 调用 `add(3, 5)`
}
📌 输出
8
✅ FuncPtr 让 ptr 变得易读,等价于 int (*ptr)(int, int);。
3. typedef 用于函数指针数组
函数指针数组允许存储多个函数,并动态选择不同的函数执行:
typedef int (*FuncPtr)(int, int); // ✅ 定义函数指针别名int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }int main() {FuncPtr operations[] = { add, subtract }; // ✅ 函数指针数组std::cout << operations[0](5, 3) << std::endl; // ✅ add(5, 3)std::cout << operations[1](5, 3) << std::endl; // ✅ subtract(5, 3)
}
📌 输出
8
2
✅ operations[0] 选择 add(),operations[1] 选择 subtract()。
4. C++11 using 替代 typedef
C++11 提供了 using 作为 typedef 的更现代的替代:
using FuncPtr = int (*)(int, int); // ✅ C++11 写法
与 typedef 等价,但语法更直观:
FuncPtr ptr = add;
🚀 推荐使用 using,可读性更强!
5. 结论
| 功能 | typedef 方式 | using 方式(C++11) |
|---|---|---|
| 定义函数指针别名 | typedef int (*FuncPtr)(int, int); | using FuncPtr = int (*)(int, int); |
| 定义函数指针数组 | FuncPtr arr[2]; | FuncPtr arr[2]; |
| 可读性 | ⭐⭐⭐ | ⭐⭐⭐⭐(更直观) |
| 推荐度 | ✅ 传统 C++ 适用 | ✅ 现代 C++ 推荐 |
✅ typedef 可以给复杂类型(如函数指针)取别名,提升可读性,但在 C++11 及以上,推荐使用 using 替代 typedef! 🚀
相关文章:
函数指针(Function Pointer)与 typedef int (*FuncPtr)(int, int);typedef与using(更推荐)
C 函数指针(Function Pointer)详解 函数指针是指向函数的指针,它可以存储函数地址,并通过该指针调用函数。函数指针在回调函数、策略模式、动态函数调用等场景中非常有用。 1. 什么是函数指针? 函数指针是一个指向函…...
【AI时代】以聊天框的模式与本地部署DeepSeek交互 (Docker方式-Open WebUI)
一、本地部署DeepSeek 参考地址:(含资源下载) https://blog.csdn.net/Bjxhub/article/details/145536134二、安装Docker https://www.docker.com/ 三、拉取Open WebUI 镜像 docker pull ghcr.io/open-webui/open-webui:main 四、启动并验证 启动: docker run …...
【Elasticsearch】监控与管理:集群监控指标
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
鸿蒙接入支付宝SDK后模拟器无法运行,报错error: install parse native so failed.
鸿蒙项目接入支付宝后,运行提示error: install parse native so failed. 该问题可能由于设备支持的 Abi 类型与 C 工程中的不匹配导致. 官网error: install parse native so failed.错误解决办法 根据官网提示在模块build-profile.json5中添加“x86_64”依然报错 问…...
react redux用法学习
参考资料: https://www.bilibili.com/video/BV1ZB4y1Z7o8 https://cn.redux.js.org/tutorials/essentials/part-5-async-logic AI工具:deepseek,通义灵码 第一天 安装相关依赖: 使用redux的中间件: npm i react-redu…...
Maven 在 Eclipse 中的使用指南
Maven 在 Eclipse 中的使用指南 引言 Maven 是一个强大的项目管理和构建自动化工具,它可以帮助开发者更高效地管理项目依赖、构建和测试。Eclipse 作为一款流行的集成开发环境(IDE),与 Maven 的结合使用大大提高了 Java 项目的开发效率。本文将详细介绍如何在 Eclipse 中…...
【Matlab优化算法-第13期】基于多目标优化算法的水库流量调度
一、前言 水库流量优化是水资源管理中的一个重要环节,通过合理调度水库流量,可以有效平衡防洪、发电和水资源利用等多方面的需求。本文将介绍一个水库流量优化模型,包括其约束条件、目标函数以及应用场景。 二、模型概述 水库流量优化模型…...
Redis 集群(Cluster)和基础的操作 部署实操篇
三主三从 集群概念 Redis 的哨兵模式,提高了系统的可用性,但是正在用来存储数据的还是 master 和 slave 节点,所有的数据都需要存储在单个 master 和 salve 节点中。 如果数据量很大,接近超出了 master / slave 所在机器的物理内…...
[2025年最新]2024.3版本idea无法安装插件问题解决
背景 随着大模型的持续发展,特别年前年后deepseek的优异表现,编程过程中,需要解决ai来辅助编程,因此需要安装一些大模型插件 问题描述 在线安装插件的时候会遇到以下问题: 1.数据一直在加载,加载的很满 2.点…...
elasticsearch安装插件analysis-ik分词器(深度研究docker内elasticsearch安装插件的位置)
最近在学习使用elasticsearch,但是在安装插件ik的时候遇到许多问题。 所以在这里开始对elasticsearch做一个深度的研究。 首先提供如下链接: https://github.com/infinilabs/analysis-ik/releases 我们下载elasticsearch-7-17-2的Linux x86_64版本 …...
golang 开启HTTP代理认证
内部网路不能直接访问外网接口,可以通过代理发送HTTP请求。 HTTP代理服务需要进行认证。 package cmdimport ("fmt""io/ioutil""log""net/http""net/url""strings" )// 推送CBC07功能 func main() {l…...
【Unity3D】UGUI的anchoredPosition锚点坐标
本文直接以实战去理解锚点坐标,围绕着将一个UI移动到另一个UI位置的需求进行说明。 (anchoredPosition)UI锚点坐标,它是UI物体的中心点坐标,以UI物体锚点为中心的坐标系得来,UI锚点坐标受锚点(Anchors Min…...
C++多态性之包含多态(一)—学习记录
一、C的包含多态 面向对象程序设计的四大特点为抽象、封装、继承和多态,其中,多态性可以提高代码的可拓展性和可维护性。 多态是指同样的消息被不同类型的对象接收时导致不同的行为。所谓消息是指对类的成员函数的调用,不同的行为是指不同的实…...
KERL文献阅读分享:知识图谱与预训练语言模型赋能会话推荐系统
标题期刊年份Knowledge Graphs and Pre-trained Language Models enhanced Representation Learning for Conversational Recommender SystemsJournal of LaTeX Class Files2021 📈研究背景 在数字时代,个性化推荐系统已经成为了我们生活的一部分。从电…...
C#、.Net 中级高级架构管理面试题杂烩
1、简述值类型和引用类型的区别 存储位置:值类型变量直接存储数据的值,通常存储在栈上;引用类型变量存储的是对象在堆上的引用地址。 内存管理:值类型的内存由系统自动管理,当超出作用域时自动释放;引用类…...
从零开始:使用Jenkins实现高效自动化部署
在这篇文章中我们将深入探讨如何通过Jenkins构建高效的自动化部署流水线,帮助团队实现从代码提交到生产环境部署的全流程自动化。无论你是Jenkins新手还是有一定经验的开发者,这篇文章都会为你提供实用的技巧和最佳实践,助你在项目部署中走得…...
Lua限流器的3种写法
学而不思则罔,思而不学则殆 引言 上篇文章讲解了Lua脚本,事务和Pipline之间的使用方式和性能差距,本篇文章将聚焦Lua脚本,我将用三种写法来展现如何实现一个Redis限流器 固定窗口限流 固定窗口限流也是最简单的限流算法&#x…...
hive的几种复杂数据类型
Hive的几种复杂数据类型 Hive 提供了几种复杂数据类型,能够支持更灵活和多样的数据存储。这些复杂数据类型对于处理嵌套数据或不规则数据特别有用。主要包括以下几种: 文章目录 Hive的几种复杂数据类型1. 数组(ARRAY)2. 结构体&a…...
序列化/反序列化与TCP通信协议
深入理解序列化/反序列化与TCP通信协议 一、序列化与反序列化 1.1 基本概念 序列化(Serialization): 将数据结构或对象状态转换为可存储/传输格式的过程反序列化(Deserialization): 将序列化后的数据恢复为原始数据结构的过程 …...
Ollama 本地部署 体验 deepseek
下载安装ollama,选择模型 进行部署 # 管理员命令行 执行 ollama run deepseek-r1:70b浏览器访问http://ip:11434/ 返回 Ollama is runninghttp://ip:11434/v1/models 返回当前部署的模型数据 下载安装CherryStudio,本地对话UI 客户端 在设置中 修改API地址&#x…...
Linux探秘坊-------4.进度条小程序
1.缓冲区 #include <stdio.h> int main() {printf("hello bite!");sleep(2);return 0; }执行此代码后,会 先停顿两秒,再打印出hello bite,但是明明打印在sleep前面,为什么会后打印呢? 因为ÿ…...
postgreSQL16.6源码安装
1.获取源码 从PostgreSQL: File Browser获取tar.bz2或者tar.gz源码 2.解压 tar xf postgresql-version.tar.bz2 roothwz-VMware-Virtual-Platform:/usr/local# tar xf postgresql-16.6.tar.bz2 roothwz-VMware-Virtual-Platform:/usr/local# ll 总计 24324 drwxr-xr-x 12 ro…...
树莓派上 基于Opencv 实现人脸检测与人脸识别
一,需求 基于树莓派4b,usb1080p摄像头,实现人脸检测与人脸识别。尝试了海陵科的模组和百度的sdk。海陵科的模组无法录入人脸,浪费了100多块钱。百度的sdk 在树莓派上也无法录入人脸,官方解决不了。最后只能用opencv自…...
vscode怎么更新github代码
vscode怎么更新github代码 打开终端: 在 VS Code 中,使用快捷键 Ctrl (Mac 上是 Cmd) 打开终端。 导航到项目目录: 确保你当前所在的终端目录是你的项目目录。如果不是,可以使用 cd 命令导航到项目目录,例如…...
Golang Web单体项目目录结构最佳实践
在Golang 开发Web 项目的过程中,如何组织目录结构是一项至关重要的任务。合理的目录结构不仅能提高代码的可维护性,还能为团队协作提供清晰的代码规范。 为什么要设计合理的目录结构? 在 Golang 项目中,代码的组织方式会影响开发…...
Zookeeper 作注册中心 和nacos 和eruka 有什么差异 ?基于什么理论选择?
目录 三者的差异 1. 设计定位与功能特性 2. 服务注册与发现机制 3. 可用性与容错性 4. 性能 选择依据 1. 业务场景 2. 可用性和一致性需求 3. 性能需求 三者的差异 1. 设计定位与功能特性 Zookeeper 设计定位:最初是为分布式应用提供协调服务的,本身并不是专门作为…...
mac下dify+deepseek部署,实现私人知识库
目前deepseek 十分火爆,本地部署实现私有知识库,帮助自己日常工作,上一篇使用工具cherry studio可以做到私人知识库。今天学习了一下,使用Dify链接deepseek,实现私人知识库,也非常不错,这里分享…...
CSS 实现下拉菜单效果实例解析
1. 引言 在 Web 开发过程中,下拉菜单是一种常见且十分实用的交互组件。很多前端教程都提供过简单的下拉菜单示例,本文将以一个简洁的实例为出发点,从 HTML 结构、CSS 样式以及整体交互逻辑三个层面进行详细解析,帮助大家理解纯 C…...
C# 比较两个List集合内容是否相同
在 C# 中,要比较两个 List<T> 集合的内容是否相同,可以通过以下几种方法: 一、非自定义类的元素比较 1. 使用 SequenceEqual 方法(顺序和内容都相等) 顺序和内容都相等:使用 SequenceEqual。 usin…...
x64、aarch64、arm与RISC-V64:详解四种处理器架构
x64、aarch64、arm与RISC-V64:详解四种处理器架构 x64架构aarch64架构ARM架构RISC-V64架构总结与展望在计算机科学领域,处理器架构是构建计算机系统的基石,它决定了计算机如何执行指令、管理内存和处理数据。x64、aarch64、arm与RISC-V64是当前主流的四种处理器架构,它们在…...
