函数指针(Function Pointer)与 typedef int (*FuncPtr)(int, int);typedef与using(更推荐)

news2025/2/12 5:08:38

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. 使用 typedefusing 简化函数指针

函数指针的语法比较复杂,可以使用 typedefusing 来简化。

(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;
}

typedefusing 让代码更简洁!


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 = 7
    std::cout << operations[1](7, 2) << std::endl;  // 7 - 2 = 5
    std::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

FuncPtrptr 变得易读,等价于 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! 🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Elasticsearch】监控与管理:集群监控指标

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

鸿蒙接入支付宝SDK后模拟器无法运行,报错error: install parse native so failed.

鸿蒙项目接入支付宝后&#xff0c;运行提示error: install parse native so failed. 该问题可能由于设备支持的 Abi 类型与 C 工程中的不匹配导致. 官网error: install parse native so failed.错误解决办法 根据官网提示在模块build-profile.json5中添加“x86_64”依然报错 问…

react redux用法学习

参考资料&#xff1a; https://www.bilibili.com/video/BV1ZB4y1Z7o8 https://cn.redux.js.org/tutorials/essentials/part-5-async-logic AI工具&#xff1a;deepseek&#xff0c;通义灵码 第一天 安装相关依赖&#xff1a; 使用redux的中间件&#xff1a; npm i react-redu…

【Matlab优化算法-第13期】基于多目标优化算法的水库流量调度

一、前言 水库流量优化是水资源管理中的一个重要环节&#xff0c;通过合理调度水库流量&#xff0c;可以有效平衡防洪、发电和水资源利用等多方面的需求。本文将介绍一个水库流量优化模型&#xff0c;包括其约束条件、目标函数以及应用场景。 二、模型概述 水库流量优化模型…

Redis 集群(Cluster)和基础的操作 部署实操篇

三主三从 集群概念 Redis 的哨兵模式&#xff0c;提高了系统的可用性&#xff0c;但是正在用来存储数据的还是 master 和 slave 节点&#xff0c;所有的数据都需要存储在单个 master 和 salve 节点中。 如果数据量很大&#xff0c;接近超出了 master / slave 所在机器的物理内…

[2025年最新]2024.3版本idea无法安装插件问题解决

背景 随着大模型的持续发展&#xff0c;特别年前年后deepseek的优异表现&#xff0c;编程过程中&#xff0c;需要解决ai来辅助编程&#xff0c;因此需要安装一些大模型插件 问题描述 在线安装插件的时候会遇到以下问题&#xff1a; 1.数据一直在加载&#xff0c;加载的很满 2.点…

elasticsearch安装插件analysis-ik分词器(深度研究docker内elasticsearch安装插件的位置)

最近在学习使用elasticsearch&#xff0c;但是在安装插件ik的时候遇到许多问题。 所以在这里开始对elasticsearch做一个深度的研究。 首先提供如下链接&#xff1a; https://github.com/infinilabs/analysis-ik/releases 我们下载elasticsearch-7-17-2的Linux x86_64版本 …

【Unity3D】UGUI的anchoredPosition锚点坐标

本文直接以实战去理解锚点坐标&#xff0c;围绕着将一个UI移动到另一个UI位置的需求进行说明。 &#xff08;anchoredPosition&#xff09;UI锚点坐标&#xff0c;它是UI物体的中心点坐标&#xff0c;以UI物体锚点为中心的坐标系得来&#xff0c;UI锚点坐标受锚点(Anchors Min…

C++多态性之包含多态(一)—学习记录

一、C的包含多态 面向对象程序设计的四大特点为抽象、封装、继承和多态&#xff0c;其中&#xff0c;多态性可以提高代码的可拓展性和可维护性。 多态是指同样的消息被不同类型的对象接收时导致不同的行为。所谓消息是指对类的成员函数的调用&#xff0c;不同的行为是指不同的实…

KERL文献阅读分享:知识图谱与预训练语言模型赋能会话推荐系统

标题期刊年份Knowledge Graphs and Pre-trained Language Models enhanced Representation Learning for Conversational Recommender SystemsJournal of LaTeX Class Files2021 &#x1f4c8;研究背景 在数字时代&#xff0c;个性化推荐系统已经成为了我们生活的一部分。从电…

从零开始:使用Jenkins实现高效自动化部署

在这篇文章中我们将深入探讨如何通过Jenkins构建高效的自动化部署流水线&#xff0c;帮助团队实现从代码提交到生产环境部署的全流程自动化。无论你是Jenkins新手还是有一定经验的开发者&#xff0c;这篇文章都会为你提供实用的技巧和最佳实践&#xff0c;助你在项目部署中走得…

hive的几种复杂数据类型

Hive的几种复杂数据类型 Hive 提供了几种复杂数据类型&#xff0c;能够支持更灵活和多样的数据存储。这些复杂数据类型对于处理嵌套数据或不规则数据特别有用。主要包括以下几种&#xff1a; 文章目录 Hive的几种复杂数据类型1. 数组&#xff08;ARRAY&#xff09;2. 结构体&a…

序列化/反序列化与TCP通信协议

深入理解序列化/反序列化与TCP通信协议 一、序列化与反序列化 1.1 基本概念 序列化&#xff08;Serialization&#xff09;: 将数据结构或对象状态转换为可存储/传输格式的过程反序列化&#xff08;Deserialization&#xff09;: 将序列化后的数据恢复为原始数据结构的过程 …

Ollama 本地部署 体验 deepseek

下载安装ollama,选择模型 进行部署 # 管理员命令行 执行 ollama run deepseek-r1:70b浏览器访问http://ip:11434/ 返回 Ollama is runninghttp://ip:11434/v1/models 返回当前部署的模型数据 下载安装CherryStudio&#xff0c;本地对话UI 客户端 在设置中 修改API地址&#x…

Linux探秘坊-------4.进度条小程序

1.缓冲区 #include <stdio.h> int main() {printf("hello bite!");sleep(2);return 0; }执行此代码后&#xff0c;会 先停顿两秒&#xff0c;再打印出hello bite&#xff0c;但是明明打印在sleep前面&#xff0c;为什么会后打印呢&#xff1f; 因为&#xff…

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 实现人脸检测与人脸识别

一&#xff0c;需求 基于树莓派4b&#xff0c;usb1080p摄像头&#xff0c;实现人脸检测与人脸识别。尝试了海陵科的模组和百度的sdk。海陵科的模组无法录入人脸&#xff0c;浪费了100多块钱。百度的sdk 在树莓派上也无法录入人脸&#xff0c;官方解决不了。最后只能用opencv自…

mac下dify+deepseek部署,实现私人知识库

目前deepseek 十分火爆&#xff0c;本地部署实现私有知识库&#xff0c;帮助自己日常工作&#xff0c;上一篇使用工具cherry studio可以做到私人知识库。今天学习了一下&#xff0c;使用Dify链接deepseek&#xff0c;实现私人知识库&#xff0c;也非常不错&#xff0c;这里分享…

CSS 实现下拉菜单效果实例解析

1. 引言 在 Web 开发过程中&#xff0c;下拉菜单是一种常见且十分实用的交互组件。很多前端教程都提供过简单的下拉菜单示例&#xff0c;本文将以一个简洁的实例为出发点&#xff0c;从 HTML 结构、CSS 样式以及整体交互逻辑三个层面进行详细解析&#xff0c;帮助大家理解纯 C…

x64、aarch64、arm与RISC-V64:详解四种处理器架构

x64、aarch64、arm与RISC-V64:详解四种处理器架构 x64架构aarch64架构ARM架构RISC-V64架构总结与展望在计算机科学领域,处理器架构是构建计算机系统的基石,它决定了计算机如何执行指令、管理内存和处理数据。x64、aarch64、arm与RISC-V64是当前主流的四种处理器架构,它们在…