6.1 函数基础

news2025/1/10 20:31:49

文章目录

      • 编写函数
      • 调用函数
      • 形参和实参
      • 函数的形参列表
      • 函数的返回类型
    • 局部对象
      • 自动对象
      • 局部静态对象
    • 函数声明
      • 在头文件中进行函数的声明
    • 分离式编译
      • 编译和链接多个源文件

一个典型的函数 定义包括以下部分:返回类型、函数名字、由0个或多个形参组成的 列表以及函数体。其中,形参以逗号隔开,形参的列表位于一对圆括号之内。函数执行的操作在语句块中说明,该语句块称为函数体。

我们通过调用运算符来执行函数。调用运算符的形式是一对圆括号,它作用于一个表达式,该表达式是函数或者指向函数的指针:圆括号之内是一个用逗号隔开的实参列表,我们用实参初始化函数的形参。调用表达式的类型就是函数的返回类型。

这边给个案例下文进行分析:(计算阶乘)

#include<iostream>

using namespace std;

int function(int val)
{
	if (val == 1 || val == 0)
		return 1;
	else
		return val * function(val - 1);
}

int main()
{
	int num = function(5);
	cout << num;
	return 0;
}

编写函数

对于编写的函数也就是上文的:

int function(int val)
{
	if (val == 1 || val == 0)
		return 1;
	else
		return val * function(val - 1);
}

这个函数说明了:这个函数的名字是function,它作用于一个整型的参数,返回的值也是一个整型的数据,return语句负责结束function并且返回相对应的值。

调用函数

对于上述的函数要调用这个函数就必须传入一个整型值。并且它是有一个返回值的,所以也需要一个东西来承接住,文章中用

int num = function(5);

来进行调用函数。

函数的调用完成两项工作:一是用实参初始化函数对应的形参,二是将控制权转移给被调用函数。此时,主调函数(main)的执行被暂时中断,被调函数(function)开始执行。

执行函数的第一步是(隐式地)定义并初始化它的形参。因此,当调用function函数时,首先创建一个名为val的int变量,然后将它初始化为调用时所用的实参5。

当遇到一条return语句时函数结束执行过程。和函数调用一样, return语句也完成两项工作:一是返回return语句中的值(如果有的话),二是将控制权从被调函数转移回主调函数。函数的返回值用于初始化调用表达式的结果,之后继续完成调用所在的表达式的剩余部分。

形参和实参

实参是形参的初始值。第一个实参初始化为第一个形参,第二个实参初始化第二个形参,以此类推。尽管实参与形参存在对应关系,但是并没有规定实参的求值顺序。编译器能以任意可行的顺序对实参求值。

实参的类型必须与对应的形参类型匹配,这一点与之前的规则是一致的,我们知道在初始化过程中初始值的类型也必须与初始化对象的类型匹配。函数有几个形参,我们就必须提供相同数量的实参(缺省函数除外)。因为函数的调用规定实参数量应与形参数量一致,所以形参一定会被初始化。

但是如果上文我们的函数调用使用:

int num = function(3,14);

这样也是对的,对于调用函数的时候,函数先去寻找有没有function(double)的函数,发现没有,就将double强转去寻找相类似的函数,发现找到了function(int)所以实际上这句话调用的是function(3),也就是进行了强行转化。

函数的形参列表

函数的形参列表可以为空,但是不能省略。要想定义一个不带形参的函数,最常用的办法是书写一个空的形参列表。不过为了与C语言兼容,也可以使用关键字void表示函数没有形参。

形参名是可选的,但是由于我们无法使用未命名的形参,所以形参一般 都应该有个名字。偶尔,==函数确实有个别形参不会被用到,则此类形参通常不命名以表示在函数体内不会使用它。==不管怎样,是否设置未命名的形参并不影响调用时提供的实参数量。即使某个形参不被函数使用,也必须为它提供一个实参。

函数的返回类型

大多数类型都能用作函数的返回类型。一种特殊的返回类型是void,它表示函数不返回任何值。函数的返回类型不能是数组类型或函数类型,但可以是指向数组或函数的指针。我们将在后文介绍如何定义一种特殊的函数,它的返回值是数组的指针(或引用),在之后将介绍如何返回指向函数的指针

局部对象

在C++语言中,名字有作用域,对象有生命周期(lifetime)。

  1. 名字的作用域是程序文本的一部分,名字在其中可见。
  2. 对象的生命周期是程序执行过程中该对象存在的一段时间。

如我们所知,函数体是一个语句块。块构成一个新的作用域,我们可以在其中定义变量。形参和函数体内部定义的变量统称为局部变量。它们对函数而言是“局部”的,仅在函数的作用域内可见,同时局部变量还会隐藏在外层作用域中同名的其他所有声明中。

在所有函数体之外定义的对象存在于程序的整个执行过程中。此类对象在程序启动时被创建,直到程序结束才会销毁。

局部变量的生命周期依赖于定义的方式。

自动对象

对于普通局部变量对应的对象来说,形参是一种自动对象。函数开始时为形参申请存储空间,因为形参定义在函数体作用域之内,所以一旦函数终止,形参也就被销毁。

我们用传递给函数的实参初始化形参对应的自动对象。对于局部变量对应的自动对象来说,则分为两种情况:如果变量定义本身含有初始值,就用这个初始值进行初始化;否则,如果变量定义本身不含初始值,执行默认初始化(也可能内部没有任何的值)。

局部静态对象

某些时候,有必要令局部变量的生命周期贯穿函数调用及之后的时间。可以将局部变量定义成static类型从而获得这样的对象。局部静态对象在程序的执行路径第一次经过对象定义语句时初始化,并且直到程序终止才被销毁,在此期间即使对象所在的函数结束执行也不会对它有影响。

样例:

#include<iostream>

using namespace std;

int function()
{
	static int i = 0;
	return i++;
}

int main()
{
	for (size_t i = 0; i < 5; i++)
	{
		cout << function()<<endl;
	}
	return 0;
}

输出结果:
在这里插入图片描述
在控制流第一次经过 i的定义之前,i被创建并初始化为0, 每次调用将i加1并返回新值。但是仅仅对于static来说,他仅仅只会定义一次,后续再次使用就相当于跳过此句话。

如果局部静态变量没有显式的初始值,它将执行值初始化,内置类型的局部静态变量初始化为0(和放在所有函数之外的变量一样)。

最后稍微总结一下:

  1. 形参:函数括号内的数据。
  2. 局部变量:语句块{}内部定义的变量。
  3. 局部静态变量:使用static定义的局部变量。

函数声明

和其他名字一样,函数的名字也必须在使用之前声明。类似于变量,函数只能定义一次,但可以声明多次。唯一的例外是虚函数,如果一个函数永远也不会被我们用到,那么它可以只有声明没有定义。

函数的声明一般用在函数的定义在你所要写的位置之后,所有需要有声明,其实完全可以将声明提到最开始的时候进行书写,这样子就不需要函数的声明了,声明的语法实际上就是去掉{程序块}的函数加个;

比如:

int function();这就是一个函数的声明

样例:

#include<iostream>

using namespace std;


int main()
{
	int function();//函数的声明
	for (size_t i = 0; i < 5; i++)
	{
		cout << function()<<endl;
	}
	return 0;
}

int function()//函数的定义
{
	static int i = 0;
	return i++;
}

函数需要声明的情况是:

  1. 函数是外部定义的, 即调用者看不到函数的实现时. 比如函数A在a.cpp中实现的, 函数B在b.cpp中实现的. 函数B要调用A,则需要先声明, 同样, A调用B也需要先声明.(对应的是分离式编译)
  2. 调用处, 函数还未实现. 比如函数A在前面. 函数B在后面. 这时A调用B就需要先声明. 反过来B调用A的话, 因为A在B的前面已经实现, 所以就可以不用声明了.(对应的是上述例子)

在头文件中进行函数的声明

如果有需要的声明,可以在头文件中进行声明。

或者说为了完成分离式编程,你在可以写一个全是函数声明的头文件来避免重复。

分离式编译

随着程序越来越复杂,我们希望把程序的各个部分分别存储在不同文件中。为了允许编写程序时按照逻辑关系将其划分开来,C++语言支持所谓的分离式编译。分离式编译允许我们把程序分割到几个文件中去,每个文件独立编译。

编译和链接多个源文件

举个例子,假设fact函数的定义位于一个名为fact.h的文件中,它的声明位于名为Chapter6.h的头文件中。显然与其他所有用到fact函数的文件一样,fact.cc应该包含Chapter6.h头文件。另外,我们在名为factMain.cc 的文件中创建main函数,main函数将调用fact函数。要生成可执行文件,必须告诉编译器我们用到的代码在哪里。这边不详细介绍,相关的可以自行去了解。这源于每个编译器的底层。

这边以一个例子进行辅助理解:

Test.h:

//Test.h
#pragma once

#include<iostream>
using namespace std;
#include<stdlib.h>

void fun();           // 仅仅只声明//1

Test.cpp:

//Test.cpp
#include"Test.h"

void fun()                 // 对函数fun()进行定义
{
    cout << "fun" << endl;
}

main.cpp:

//main.cpp
#include"Test.h"

int main()
{
    fun();              //调用fun()函数
    return 0;
}

我们可以把1注释掉,可以简单的发现这个声明是必须的,因为这个声明表示了fun函数是一个外部函数(fun函数定义在Test.cpp中,而且main.cpp完全没有它的定义)。实际上这个过程就像extern int i;一样,声明i是外部来的变量,从别的cpp中拿值。

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

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

相关文章

数据库,计算机网络、操作系统刷题笔记20

数据库&#xff0c;计算机网络、操作系统刷题笔记20 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle…

第三十章 数论——扩展中国剩余定理

第三十章 数论——扩展中国剩余定理一、中国剩余定理的弊端二、扩展中国剩余定理1、作用2、内容3、问题4、代码一、中国剩余定理的弊端 在第二十九章中&#xff0c;作者详细地讲解了中国剩余定理的使用&#xff0c;在开始本章节的讲解之前&#xff0c;建议读者先去看上一章节的…

Tensorflow2 图像分类-Flowers数据深度学习模型保存、读取、参数查看和图像预测

目录 1.原文完整代码 1.1 模型运行参数总结 1.2模型训练效果 ​编辑2.模型的保存 3.读取模型model 4.使用模型进行图片预测 5.补充 如何查看保存模型参数 5.1 model_weights 5.2 optimizer_weights 使用之前一篇代码&#xff1a; 原文链接&#xff1a;Tensorflow2 图像分…

English Learning - L1-7 介词 2022.12.26 周一

English Learning - L1-7 介词 2022.12.26 周一7 介词7.1 介词功能 1 - 表示动作的方向&#xff0c;范围和程度7.2 介词功能 2 - 胶水词&#xff0c;链接不同的名词7.3 介词功能 3 - 与 be 动词连用代替动词7.4 江南四大介词on核心意义&#xff1a;在。。。上; 在&#xff08;某…

融云 x OHLA:「社交+游戏」双轮驱动,逐鹿中东陌生人社交

完整报告&#xff0c;关注公众号文章限免下载 走过十多年的出海历程&#xff0c;中国创业者面临的机遇和挑战正在发生根本性变化。TikTok、SHEIN 在全球大获全胜的背后&#xff0c;不仅有中国产业链成熟、工程师红利的厚积薄发&#xff0c;也有一代代出海人布局全球商业路径的思…

Ubuntu20.04部署KVM并安装Ubuntu Server 20.04

kvm虚拟化技术 KVM介绍 KVM是Linux开源社区大力支持的虚拟化技术&#xff0c;基于Intel和AMD的硬件虚拟化技术。KVM&#xff08;Kernel-bashdVirtual Machine&#xff0c;即基于内核的虚拟机&#xff09;&#xff0c;它是用于Linux内核中的虚拟化环境设施&#xff0c;是Linux…

python:什么?你听MP3居然还要付费?看我一键......

前言 大家早好、午好、晚好吖 ❤ ~ 在我们上班空闲\游玩\散步的时候,总会习惯的拿出手机放首音乐来听一听 但是吧,有时候我们听一首歌起劲的时候,它会你提醒你 这时候怎么办呢&#xff1f;通常我们是下一首&#xff0c;或者充值 但是手头不宽裕但又想听怎么办&#xff1f; …

JavaEE-Spring(IoC控制反转,DI依赖注入,Spring项目创建和基本使用,ApplicationContext和BeanFactory的区别)

文章目录1. IoCDI2. Spring项目创建和使用ApplicationContext和BeanFactory的区别1. IoC Spring是一个包含多个工具方法的IoC容器 tomcat是web容器 List/Map是数据存储容器 IoC&#xff1a;Inversion of Control&#xff08;控制反转&#xff09; 将对象的控制权交给Spring&…

RK3399+PCIe+FPGA 在高速AD采样中的应用

一、需求 要实现高速AD/DA的数据采集&#xff0c;并发送到高性能arm核进行数据处理&#xff1b; 方案RK3399pcieFPGAAD/DA。 二、器件介绍 一、RK3399 RK3399是一款低功耗、高性能处理器&#xff0c;用于计算、个人移动互联网设备和其他智能设备应用。基于Big.Little架构&…

计算机发展史之查尔斯·巴贝奇

查尔斯巴贝奇&#xff08;Charles Babbage&#xff0c;1791年12月26日—1871年10月18日&#xff09;是一名英国数学家、发明家、科学家&#xff0c;科学管理的先驱者&#xff0c;出生于一个富有的银行家的家庭&#xff0c;曾就读于剑桥大学三一学院。 他在24岁时就被选为英国皇…

智慧医院数据可视化(数据大屏)

本次分享的作品是用软件Axure8.0&#xff08;兼容9和10&#xff09;制作的针对智慧医院设计的数据可视化大屏&#xff0c;其作品内容主要是对医院的运营情况、门诊、住院、手术、药品、医务、医疗设备、卫生耗材以及医疗质量数据进行综合可视分析。 运营情况:对医院的整体数据…

左神算法学习:第一天-------位运算

前言 位运算是在算法设计中的一种非常重要和高效的方法&#xff0c;常见的有与运算&#xff0c;非运算&#xff0c;异或运算。我们常用的比较多的可能就是异或运算&#xff0c;又叫无进位相加。 1.1 取非运算----&#xff08;~&#xff09; 取非运算其实就是和我们的无符号数…

cadence SPB17.4 - 用元件管理器来更新原理图中的元件属性信息

文章目录cadence SPB17.4 - 用元件管理器来更新原理图中的元件信息概述笔记修正原理图库修正CIS库的元件登记表ENDcadence SPB17.4 - 用元件管理器来更新原理图中的元件信息 概述 画好图后, 出了BOM. 同学指出BOM中有些元件型号信息不合适, 影响元件购买, 想改一下. 更新了原…

设计模式-桥接、职责链、中介

前言 本文为datawhale2022年12月组队学习《大话设计模式》task6打卡学习。 【教程地址】https://github.com/datawhalechina/sweetalk-design-pattern 一、桥接模式 1.1 基本定义 桥接模式&#xff08;Bridge Pattern&#xff09;又称为柄体(Handle and Body)模式或接口(In…

第十二讲:生成树概念及STP技术应用

在传统的交换网络中&#xff0c;设备通过单条链路进行连接&#xff0c;当某一个点或是某一个链路发生故障时可能导致网络无法访问&#xff0c;解决这种问题的办法是在网络中提供冗余链路&#xff0c;但是交换机网络中的冗余链路会产生广播风暴、MAC地址失效等现象&#xff0c;最…

StarRocks 统计信息和 Cost 估算

导读&#xff1a;欢迎来到 StarRocks 源码解析系列文章&#xff0c;我们将为你全方位揭晓 StarRocks 背后的技术原理和实践细节&#xff0c;助你逐步了解这款明星开源数据库产品。本期 StarRocks 技术内幕将主要介绍 StarRocks 统计信息和 Cost 估算。 1.背景 在学习本文之前&…

mysql搭建主从复制

Mysql主从复制搭建过程&#xff1a; 主从需同步时间&#xff0c;主开启ntpd&#xff08;ntp网络时间协议&#xff0c;它的端口号udp123&#xff09;服务-----修改配置&#xff0c;从通过/usr/sbin/ntpdate 主ip(ntpdate包需要提前安装)&#xff1b;主&#xff1a;开启中继二进…

整数划分问题(Java递归)

整数划分问题&#xff08;Java递归&#xff09; 文章目录整数划分问题&#xff08;Java递归&#xff09;0、 问题描述1、递归式2、代码3、参考0、 问题描述 整数划分问题 将正整数n表示成一系列正整数之和&#xff1a;nn1n2…nk&#xff0c;其中n1≥n2≥…≥nk≥1&#xff0c;k…

数字校园建设方案技术建议书

【版权声明】本资料来源网络&#xff0c;仅用于行业知识分享&#xff0c;供个人学习参考&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间进行删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 1.1 华为数字化…

“设计”小哥转行5G网络优化工程师!从零开始,三个月实现逆风翻盘~

5G网络优化&#xff0c;一个陌生的领域&#xff0c;对于一个毫无经验的小白来说&#xff0c;选择转行必定是需要勇气和决心的。好在&#xff0c;在决定选择5G网络优化的这一段时间里&#xff0c;老师给予了我最大的帮助和支持&#xff0c;包括从授课&#xff0c;到练习&#xf…