C++自定义函数详解

个人主页:PingdiGuo_guo
收录专栏:C++干货专栏

铁汁们新年好呀,今天我们来了解自定义函数。
文章目录
1.数学中的函数
2.什么是自定义函数
3.自定义函数如何使用?
4.值传递和引用传递(形参和实参区分)
1.值传递
2. 引用传递
3. 形参与实参的区别
5.自定义递归函数
6.嵌套调用和链式调用
1.链式调用
2.嵌套调用
7.自定义函数和库函数的对比
8.自定义函数的练习
9.总结
1.数学中的函数
在数学中,函数是一种基本的数学对象,它建立了一个集合(称为定义域)中的每个元素与另一个集合(称为值域)中的唯一元素之间的对应关系。简单地说,函数就是一个规则,它接收一个或多个输入值(也称为自变量),并据此产生一个确定的输出值(称为函数值或因变量)。
数学上的函数通常用 ( f ) 表示,并写作 ( y = f(x) ),这里的 ( x ) 是自变量,( y ) 是相应于 ( x ) 的函数值。例如,线性函数 ( f(x) = mx + b ) 就是一条直线的方程,其中 ( m ) 是斜率,( b ) 是截域。

2.什么是自定义函数
自定义函数是在C++或其他编程语言中由程序员自行创建的函数,用于封装一组操作或计算逻辑,以便在多个地方重复使用或者模块化代码。自定义函数允许开发者按照自己的需求来定制功能,并且可以根据程序的具体情况调整其行为。
3.自定义函数如何使用?
1. 声明函数原型:
在函数体之前(通常在头文件或源文件的开始部分),你需要声明函数,包括返回类型、函数名以及参数列表(如果有的话):
// 声明一个自定义函数原型
double calculateArea(double radius);
这个例子声明了一个名为calculateArea的函数,它接受一个double类型的参数(半径),并返回一个double类型的值(面积)。
2. 定义函数体:
在函数声明之后,你需要定义函数的实际实现,即写出完成特定任务的代码块:
// 定义函数体
double calculateArea(double radius) {
double area = 3.14159 * radius * radius;
return area;
}
3. 调用函数:
在程序的适当位置,你可以像使用库函数一样调用自定义函数:
int main() {
double myRadius = 5.0;
double result = calculateArea(myRadius);
cout << "The area of the circle with radius " << myRadius << " is: " << result << endl;
return 0;
}
4.值传递和引用传递(形参和实参区分)
1.值传递
- 当函数通过值传递方式接收参数时,它会创建实参的副本(复制一份实参的值)并将这个副本传递给函数内部的形参。
- 形参的变化不会影响实参,因为两者存储在不同的内存位置。
- 值传递通常适用于不需要修改实参值的情况。
示例:
void swapByValue(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
swapByValue(x, y); // 调用函数后,x和y的值不变,因为交换的是函数内部形参的值
}
2. 引用传递
- 引用传递是将实参的引用(也就是实参的别名)传递给函数的形参,这样形参就直接指向实参的内存地址。
- 如果在函数内部改变了引用类型的形参,那么相应地,实参的值也会被修改。
- 引用传递常用于需要更改实参或避免大型数据结构复制的成本时。
示例:
void swapByReference(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 10, y = 20;
swapByReference(x, y); // 调用函数后,x和y的值会互换,因为函数内部修改的是实参的内存
}
3. 形参与实参的区别
- 实参(Actual Parameter):在函数调用过程中,传递给函数的实际值。例如上面例子中的 x和 y 就是实参。
- 形参(Formal Parameter):在函数定义中,用来接收传递进来的值的变量。如上述例子中的 a 和 b 是形参,它们在函数内部代表了从外部传入的值。
总结来说,在函数调用过程中,实参是实际提供的值,而形参是函数声明中用来接收这些值的地方。在C++中,值传递和引用传递决定了函数操作的是实参的副本还是实参本身。
5.自定义递归函数
递归调用函数是在函数内部调用自身的一种编程技术。这种技术在解决具有自我重复性质的问题时非常有用,如树的遍历、动态规划中的某些子问题解法、分治算法中的问题拆解等。
递归函数通常包含两个基本部分:
- 基本情况(Base Case):这是递归结束的条件,即当达到某个特定条件时,不再进行下一层递归调用,而是直接返回一个确定的结果。
- 递归步骤(Recursive Step):在此阶段,函数通过调用自身来解决规模更小的相同问题,直到满足基本情况为止。
下面是一个简单的递归函数示例,计算阶乘(Factorial):
#include <iostream>// 递归函数实现阶乘
int factorial(int n) {
// 基本情况:0的阶乘为1
if (n == 0)
return 1;
// 递归步骤:n的阶乘等于n乘以(n-1)的阶乘
else
return n * factorial(n - 1);
}int main() {
int num = 5;
std::cout << "The factorial of " << num << " is: " << factorial(num) << std::endl;
return 0;
}
在这个例子中,factorial 函数在每次递归调用时都会将问题规模缩小(减少参数n的值),直到遇到基本情况n为0时停止递归,然后逐层返回计算结果。
6.嵌套调用和链式调用
1.链式调用
链式调用是一种编程风格,可以在调用多个方法时使用点操作符将它们连接在一起,形成一个链。在每个方法调用后,都会返回一个对象,可以继续调用其他方法。这样就可以在一行代码中实现多个方法的调用,使代码更加简洁和可读性更高。
步骤一:定义一个支持链式访问的类
class Chainable {
public:
// 构造函数
Chainable(int initial_value) : value(initial_value) {}// 第一个链式方法(假设增加值)
Chainable& increment(int step = 1) {
value += step;
return *this; // 返回当前对象的引用以支持链式调用
}// 第二个链式方法(假设加倍)
Chainable& doubleValue() {
value *= 2;
return *this;
}
private:
int value;
};
步骤二:创建对象并开始链式调用
int main() {
// 创建Chainable对象
Chainable obj(5);// 链式访问与调用
obj.increment(3).doubleValue();// 这里原本可能还有其他方法继续调用...
// ...// 最终可以验证对象的值
std::cout << "Final value: " << obj.value << std::endl;return 0;
}
在上述代码中,首先定义了一个名为Chainable的类,它有两个链式方法:increment()和doubleValue()。这两个方法都在执行相应的操作之后返回了对当前对象的引用,使得可以连续调用这些方法,形成链式调用。在main()函数中展示了如何使用这种方式连续调用两个方法来处理同一个对象。
2.嵌套调用
嵌套调用是指在一个方法内部调用另一个方法,并且被调用的方法又可以继续调用其他方法,形成多层嵌套的调用关系。嵌套调用可以在程序中实现复杂的逻辑和功能,将代码进行模块化和组合,提高代码的可复用性和可维护性。
在嵌套调用中,每个方法的返回值可以作为下一个方法的参数,这样可以将多个方法串联起来,实现一系列的操作。嵌套调用的层级可以根据具体需求进行设计,可以是两层、三层,甚至更多。
步骤1:定义一个包含内部函数的外部函数:
void outerFunction(int x) {
// ...
void innerFunction();
// ...
}
步骤2:定义内部函数的具体实现:
void outerFunction(int x) {
std::cout << "In outer function with x = " << x << std::endl;void innerFunction() {
std::cout << "In inner function." << std::endl;
}
}
步骤3:在外部函数内部调用内部函数:
void outerFunction(int x) {
// ...
innerFunction(); // 这里是嵌套调用发生的地方
// ...
}
步骤4:完整外部函数及其调用示例:
void outerFunction(int x) {
std::cout << "In outer function with x = " << x << std::endl;void innerFunction() {
std::cout << "In inner function." << std::endl;
}innerFunction();std::cout << "Continuing in outer function after inner call." << std::endl;
}int main() {
outerFunction(5); // 在主函数中调用outerFunction
return 0;
}
输出:
In outer function with x = 5
In inner function.
Continuing in outer function after inner call.
7.自定义函数和库函数的对比
- 自定义函数:
- 由程序员根据具体需求编写。
- 可以自由命名,具有高度灵活性。
- 具体实现完全取决于程序员,可修改、优化或扩展。
- 只能在包含它们的源文件或链接到它们的库中调用。
- 库函数:
- 预先编写好的、经过充分测试的标准函数,通常由语言本身或第三方库提供。
- 名称和功能通常是标准化的,如C++标准库中的std::sort()、std::cos()等。
- 不需要程序员重新实现,只需包含适当的头文件并在程序中正确调用即可。
- 通常跨平台兼容性更好,因为它们遵循语言规范和标准。
- 提供的功能广泛多样,涵盖基础数据结构操作、数学计算、输入/输出处理等多个方面。
总结来说,自定义函数的核心价值在于它可以针对性地解决特定的问题,并且有助于提高代码的复用性和组织性;而库函数则是为了提供通用的、高效的功能组件,减少重复劳动,提升开发效率和程序质量。
8.自定义函数的练习
假设我们要编写一个C++函数,它接受两个整数作为参数,返回它们的最大公约数(Greatest Common Divisor, GCD)。这个功能可以通过使用欧几里得算法(Euclidean algorithm)来实现。下面是这个函数的定义和使用示例:
#include <iostream>// 自定义函数:计算两个整数的最大公约数
int gcd(int a, int b) {
// 边界条件:如果b为0,则a就是最大公约数
if (b == 0)
return a;// 否则,递归地计算(a mod b)和b的最大公约数
return gcd(b, a % b);
}int main() {
int num1 ,num2 ;
std::cin>>num1>>num2;// 调用自定义函数并输出结果
std::cout << "The Greatest Common Divisor (GCD) of " << num1 << " and " << num2 << " is: " << gcd(num1, num2) << std::endl;return 0;
}
上述代码首先定义了一个名为gcd的函数,该函数采用两个整数作为参数,并使用递归方法找到它们的最大公约数。在main函数中,我们创建了两个变量并调用了gcd函数来计算它们的最大公约数,最后将结果输出到控制台。

9.总结
本篇博客到这里就结束了,感谢大家的支持与观看,如果有好的建议欢迎留言,谢谢大家啦!
相关文章:
C++自定义函数详解
个人主页:PingdiGuo_guo 收录专栏:C干货专栏 铁汁们新年好呀,今天我们来了解自定义函数。 文章目录 1.数学中的函数 2.什么是自定义函数 3.自定义函数如何使用? 4.值传递和引用传递(形参和实参区分) …...
flask+vue+python跨区通勤人员健康体检预约管理系统
跨区通勤人员健康管理系统设计的目的是为用户提供体检项目等功能。 与其它应用程序相比,跨区通勤人员健康的设计主要面向于跨区通勤人员,旨在为管理员和用户提供一个跨区通勤人员健康管理系统。用户可以通过系统及时查看体检预约等。 跨区通勤人员健康管…...
Spring Boot动态加载Jar包与动态配置技术探究
Spring Boot动态加载Jar包与动态配置技术探究 1. 引言 在当今快节奏的软件开发领域,高效的开发框架是保持竞争力的关键。Spring Boot作为一款快速开发框架,以其简化配置、内嵌Web服务器、强大的开发工具等特性,成为众多开发者的首选。其背后…...
Lua metatable metamethod
示例代码 《programming in lua》里有一个案例很详细,就是写一个集合类的table,其负责筛选出table中不重复的元素并组合成一个新的table。本人按照自己的方式默写了一次,结果发现大差不差,代码如下: Set {} --集合--…...
HCIA-HarmonyOS设备开发认证V2.0-3.2.轻量系统内核基础-任务管理
目录 一、任务管理1.1、任务状态1.2、任务基本概念1.3、任务管理使用说明1.4、任务开发流程1.5、任务管理接口 一、任务管理 从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。 O…...
中小型网络系统总体规划与设计方法
目录 1.基于网络的信息系统基本结构 2.网络需求调研与系统设计原则 3.网络用户调查 4.网络节点地理位置分布情况 5.网络需求详细分析 6.应用概要分析 7.网络工程设计总体目标与设计原则 8.网络结构与拓扑构型设计方法 9.核心层网络结构设计 10.接入核心路由器 11.汇聚…...
以管理员权限删除某文件夹
到开始菜单中找到—命令提示符—右击以管理员运行 使用:del /f /s /q “文件夹位置” 例:del /f /s /q "C:\Program Files (x86)\my_code\.git"...
JenkinsGitLab完成自动化构建部署
关于GitLab安装:GitLab安装-CSDN博客 Docker中安装GitLab:Docker下安装GitLab-CSDN博客 安装JenKins Jenkins官网:Jenkins 中文版:Jenkins 安装时候中文页面的war包下不来 在英文页面 记得装JDK8以上 JenKins使用java写的 运行JenKins需要JDK环境 我这里已经装好了 将下…...
JVM 性能调优 - 参数基础(2)
查看 JDK 版本 $ java -version java version "1.8.0_151" Java(TM) SE Runtime Environment (build 1.8.0_151-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode) 查看 Java 帮助文档 $ java -help 用法: java [-options] class [args...] …...
大型软件编程实例分享,诊所门诊处方笺管理系统多台电脑同时使用的软件教程
大型软件编程实例分享,诊所门诊处方笺管理系统多台电脑同时使用的软件教程 一、前言 以下教程以 佳易王诊所门诊电子处方管理系统V17.2 为例说明 软件资源可以点击最下方官网卡片了解详情 软件左侧为导航栏 1、系统参数设置:可以设置打印等参数 2、…...
Java基于微信小程序的医院挂号系统
文章目录 1 简介2 技术栈3 系统目标3.2 系统功能需求分析3.2.1 功能需求分析 4 系统模块设计4.1 数据库模块设计 5 系统的实现5.1 微信小程序个人中心5.2 科**室内容查看的实现**5.3 预约挂号的实现5.4 后台管理界面实现5.5 医生预约管理5.6 医生信息管理 参考文献7 推荐阅读8 …...
你是在独立思考,还是在被洗脑?
你有过这样的经历吗? 老板走过来,急匆匆丢给你一句:帮我整理一下那个客户的资料,下午给我。你抬头,应道「好好好」。老板扬长而去。你转念一想: 等等,哪个客户?什么资料?…...
在django中集成markdown文本框
首先需要下载开源组件:http://editor.md.ipandao.com/,可能需要挂梯子。 百度网盘: 链接:https://pan.baidu.com/s/1D9o3P8EQDqSqfhAw10kYkw 提取码:eric 1.在html代码中生成一个div,ideditor <div c…...
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Slider组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Slider组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Slider组件 滑动条组件,通常用于快速调节设置值,如音量调…...
django admin 自定义界面时丢失左侧导航 nav_sidebar
只显示了自定义模板的内容,左侧导航没有显示出来。 原因:context 漏掉了,要补上。 # 错误写法(左侧导航不显示)def changelist_view(self, request, extra_contextNone):form CsvImportForm()payload {"form&qu…...
JSP原理简述
JSP动态网页技术,可以定义html,css,js等静态内容,还可以定义java代码等动态内容。 注意导入坐标时,JSP的scope标签是provided,和servlet一样,否则会报错。 JSP本质上就是一个Servlet,…...
C/C++ - 异常处理
目录 错误处理 异常处理 异常传播 异常规划 标准异常 自定异常 错误处理 在C语言中,错误通常通过函数的返回值来表示。 错误返回值 对于能返回特殊值(如NULL或负值)的函数,在调用时检查这些值来处理错误。 #include <st…...
十、项目开发总结报告(软件工程)
1.引言 1.1编写目的 1.2项目背景 1.3定义 1.4参考资料 2.开发结果 2.1产品 2.2主要功能及性能 2.3所用工时 2.4所用机时 2.5进度 2.6费用 3.评价 3.1生产率评价 3.2技术方案评价 3.3产品质量评价 4ÿ…...
在 VMware 虚拟机上安装 CentOS系统 完整(全图文)教程
一、前期准备: 1.安装VMware 虚拟机软件(不在讲解,可自行去下载安装)。官网:https://customerconnect.vmware.com/cn/downloads/details?downloadGroupWKST-PLAYER-1750&productId1377&rPId111471 2.下载iso…...
吉他学习:右手拨弦方法,右手拨弦训练 左手按弦方法
第六课 右手拨弦方法https://m.lizhiweike.com/lecture2/29362775 第七课 右手拨弦训练https://m.lizhiweike.com/lecture2/29362708...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
