【C++养成计划】深入浅出——函数(Day6)

写在前面:大家好!我是【AI 菌】,一枚爱弹吉他的程序员。我热爱AI、热爱分享、热爱开源! 这博客是我对学习的一点总结与记录。如果您也对 深度学习、机器视觉、算法、Python、C++ 感兴趣,可以关注我的动态,我们一起学习,一起进步~
我的博客地址为:【AI 菌】的博客

上一篇:【C++养成计划】控制程序流程——判断与循环(Day5)
昨天,我们学习了C++程序中的两大控制流程:判断和循环。今天,我们来学习编程语言中一个很重要的知识板块:函数


1. 初识函数

一说到函数,对于编程小白,可能首先联想到的是数学中的函数公式: y = f ( x ) y=f(x) 。其实呢?C++函数与数学函数式子是有一些相通之处,比如,它们一般都有着输入和输出;函数式中的映射关系,对应到C++函数中就是一种逻辑关系。
不同的是,在C++中,函数是一组一起执行一个任务的语句。每个 C++ 程序都至少有一个函数,即主函数 main() ,并且程序从主函数处开始执行。具体可参见:【C++养成计划】基本语法(Day2)

(1) 为何需要函数

其实,对于小型的应用程序来说,完全可以使用main()实现所有功能。但是当程序越来越大,越来越复杂时,若想要main()中的代码依然保持简洁、逻辑清晰易读,就必须使用函数了
函数能够很好地划分和组织程序的执行逻辑。通过使用函数,可以将原本复杂冗长的程序划分为依次调用的程序块。

(2) 函数定义

在C++ 中,函数定义的一般形式如下:

return_type function_name(parameter list)
{
	函数主体
}

由此可知,函数主要有如下4个组成部分:

  1. 返回类型 return_type。是指函数返回值的数据类型,一个函数可以返回一个值。有些函数只执行某些操作不返回值,那么返回类型要设置为viod
  2. 函数名称 function_name。就是函数的名字,由我们自己设定,在调用函数时用到。
  3. 参数列表 parameter list。参数就像是占位符。当函数被调用时,你向参数传递一个值,这个值被称为实际参数。参数列表包括函数参数的类型、顺序、数量。参数是可选的,也就是说,函数也可以不包含参数。
  4. 函数主体。是函数的主体结构,由执行一个任务的若干语句构成。

下面举一个简单的例子,用函数实现:计算圆形的面积

#include<iostream>
using namespace std;

const double Pi =3.14;
//定义Area_circle函数,实现对圆求面积
double Area_circle(double r)
{
	return Pi*r*r;  //返回圆的面积 
}

int main()
{
	cout<<"请输入圆形的半径radius:";
	double radius=0; //初始化半径 
	cin>>radius;     //输入半径 
	cout<<"该圆的面积是:"<<Area_circle(radius)<<endl;
	return 0;
} 

运行结果如下:
在这里插入图片描述

(3) 函数声明

函数声明会告诉编译器函数名称及如何调用函数。函数声明包括以下几个部分:

return_type function_name(parameter list);//函数声明

很容易看出,函数的声明和上面函数定义中的函数头一致,不同的是,句末要加上一个分号。因此,针对上面计算圆形的面积的例子,Area_circle()函数声明形式如下:

double Area_circle(double r);

在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:

double Area_circle(double);

函数声明最常用的两种情形:

  1. 若函数实现在mian()函数之后,当main()中需要调用该函数时,我们需要程序中main()前的位置提前声明该函数。我们还是以计算圆形的面积为例:
#include<iostream>
using namespace std;

const double Pi =3.14;
double Area_circle(double r); //函数声明 

int main()
{
	cout<<"请输入圆形的半径radius:";
	double radius=0; //初始化半径 
	cin>>radius;     //输入半径 
	cout<<"该圆的面积是:"<<Area_circle(radius)<<endl;
	return 0;
} 

double Area_circle(double r)
{
	return Pi*r*r;  //返回圆的面积 
}
  1. 当你在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。在这种情况下,你应该在调用函数的文件顶部声明函数。

(4) 函数调用

创建 C++ 函数时,会定义函数做什么,然后通过调用函数来完成已定义的任务。
调用函数时,传递所需参数,如果函数返回一个值,则可以存储该函数返回的值。我们还是以计算圆形的面积为例:

#include<iostream>
using namespace std;

const double Pi =3.14;
double Area_circle(double r); //函数声明 

int main()
{
	cout<<"请输入圆形的半径radius:";
	double radius=0,area=0; //初始化半径 、面积 
	cin>>radius;     //输入半径 
	area=Area_circle(radius);  //将函数的返回值给area 
	cout<<"该圆的面积是:"<<area<<endl;
	return 0;
} 

double Area_circle(double r)
{
	double S=Pi*r*r;  //就算圆的面积 
	return S;  //返回面积S 
}

运行结果:
在这里插入图片描述

(5) 形参与实参

如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。
形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁
比如,前面讲到的函数定义和函数声明中的参数列表中的变量就是形参
当调用函数时,我们需要用到实参。在调用函数的过程中,编译器会自动将实参传递给形参,然后执行函数体。

2. 带默认值的参数

在前面计算圆形的面积是例子中,我们将Pi声明为常量,因此后面就不能对其进行修改了。那么,当我们希望得到更高或更低的精度时,就不能为力了。为了解决这种问题,我们可以给函数Area_circle()新增一个表示Pi的参数,并将其设置为默认值。比如:

double Area_circle(double r, double Pi=3.14);

注意,第二个参数Pi的默认值是3.14。对调用者来说,这个参数是可选的,因此仍可使用下面的语句来调用Area_circle():

Area_circle(radius); //这里省略了第二个参数,因此将使用默认值Pi=3.14

如果,我们想得到更高的精度。在调用函数时,可以提供Pi的值,指定要实际要用的Pi值。指定的Pi值会覆盖默认值。比如:

Area_circle(radius, 3.1416); //指定Pi=3.1416,替代原来的默认值

下面,仍以计算圆形的面积为例,演示如何编写包含默认值的函数。

#include<iostream>
using namespace std;

double Area_circle(double r, double Pi=3.14); //函数声明 
int main()
{
	cout<<"请输入圆形的半径radius:";
	double radius=0,area=0; //初始化半径 、面积 
	cin>>radius;     //输入半径 
	area=Area_circle(radius);  //将函数的返回值给area 
	cout<<"使用默认值Pi,该圆的面积是:"<<area<<endl;
	
	area=Area_circle(radius, 3.1416);
	cout<<"指定Pi=3.1416后,该圆的面积是:"<<area<<endl;
	return 0;
} 

double Area_circle(double r, double Pi)
{
	double S=Pi*r*r;  //就算圆的面积 
	return S;  //返回面积S 
}

运行结果:
在这里插入图片描述

3. 递归函数

在有些情况下,可让函数调用它自己,这样的函数称为递归函数。递归函数必须有明确的退出条件,满足这种条件后,函数将返回,而不再调用自己。
在计算斐波那契数列时,递归函数很有用。
Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1。
使用递归函数实现如下:

#include <iostream>
using namespace std;

int Fibonacci(int n)   //Fibonacci数列函数 
{
	if(n==1||n==2)
		return 1;
	else
		return Fibonacci(n-1)+Fibonacci(n-2);
}

int main()
{
	int n=0;
	cin>>n;
	cout<<Fibonacci(n);  //输出Fibonacci数列第n个数 
	return 0;
}

4. 使用函数处理不同类型的数据

并不是每次只能给函数传递一个值,还可以将数组等传递给函数。这样可在函数中操纵更多的数据和参数。

(1) 函数重载

名称和返回类型相同,但是参数不同的函数被称为重载函数
在程序中,如果需要使用不同的参数调用具有特定名称和返回类型的函数,重载函数将很实用。
下面举个例子,计算圆和圆柱的面积。计算圆面积的函数需要一个参数——半径r,而计算圆柱面积的函数还需要一个参数——高度h。这两个函数需要返回的数据类型相同,都是面积。在C++中,我们可以定义两个重载的函数,它们都叫Area,返回类型都是double,但第一个函数仅接受r为参数,第二个接受r、h作为参数。

#include<iostream>
using namespace std;

const double Pi=3.14;
double Area(double r);
double Area(double r, double h);
int main()
{
	int r=0,h=0;
	cout<<"输入圆柱体的半径r和高h:";
	cin>>r>>h;
	cout<<"圆的面积是:"<<Area(r)<<endl;
	cout<<"圆柱的表面积是:"<<Area(r,h);
	return 0; 
}

double Area(double r) //计算圆的面积 
{
	return Pi*r*r; 
}

double Area(double r, double h) //计算圆柱的表面积 
{
	return 2*Area(r)+2*Pi*r*h;
}

运行结果:
在这里插入图片描述

(2) 将数组传递给函数

显示一个数组的函数类似于下面这样:

//第一个参数表示输入的是数组,第二个参数指出了数组的长度,以免使用数组时越界
void ShowArr(int NumArr[], int length);

下面,举例显示整型数组和字符数组中的每个元素:

#include<iostream>
using namespace std;

void ShowArr(int NumArr[], int length)
{
	for(int i=0;i<length;i++)
		cout<<NumArr[i]<<" ";
} 

void ShowArr(char CharArr[], int length)
{
	for(int i=0;i<length;i++)
		cout<<CharArr[i]<<" ";
}

int main()
{
	int Numbers[5]={0,1,2,3,4};
	ShowArr(Numbers, 5);
	cout<<endl;
	char Characters[6]={'H','E','L','L','O','\0'};
	ShowArr(Characters,6);
	return 0;
}

运行结果:
在这里插入图片描述

(3) 按引用传递参数

有时候,你希望函数修改的变量能在其外部也可用,为此,可将形参的类型声明为引用,下面以Area()函数计算面积为例,以参数的方式按引用返回它:

void Area(double r, double& result)
{
	result=Pi*r*r;
}

其中符号&,它告诉编译器,不要将第二个实参复制给函数,而将指向该实参的引用传递给函数
因此,该函数的返回类型是void,因为该函数不再通过返回值提供计算得到的面积,而是按引用以输出参数的方式提供它。
下面显示如何按引用返回圆的面积:

#include<iostream>
using namespace std;

const double Pi=3.14;
void Area(double r, double& result)
{
	result=Pi*r*r;
}

int main()
{
	cout<<"输入半径radius:";
	double radius=0;
	cin>>radius;
	double GetResult=0;
	Area(radius,GetResult);
	cout<<"圆的面积是:"<<GetResult<<endl;
	return 0;
}

运行结果:
在这里插入图片描述

原创文章 63 获赞 935 访问量 2万+

猜你喜欢

转载自blog.csdn.net/wjinjie/article/details/105813330