C++语言-7-函数的自定义与函数的类型

本章学习函数相关知识。


采用以下程序段进行说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
int f(double x)
{
int a=x;
return a;
}
int main()
{
double a;
cin>>a;
cout<<f(a);
return 0;
}

样例输入1:1.1

样例输出1:1

样例输入2:0.9

样例输出2:0

可以看出,我们在公共域(又称全局)里定义了两个函数,一个是int类型的f(自带一个参数,是double类型的x),另一个就是main。

main就不多说了,毕竟int main()是强制要求,不能改动。但是这个f就很有意思了。

首先,我们学到过在公共域直接int f的话表示定义一个int类型的名为f的变量,但现在为什么是个函数呢?那就是因为f后面的小括号了。那么就有以下定义及使用规范四点。

  1. 满足形如【数据类型 名称(参数列表)】的程序段,就是函数。
  2. 自定义函数的函数体只能写在公共域或自定义类型内。其中,当自定义函数的函数体写在公共域内时:
    1. 若自定义函数的函数体写在main函数之前,则可以不在main函数里写其定义语句,因为其函数体那边就已经定义了。
    2. 若自定义函数的函数体写在main函数之后,则必须在main函数里写其定义语句。总之就是必须满足先定义再使用。
    3. 只要是函数,就必须使用大括号来告诉程序哪些语句属于这个函数。
    4. 小括号里可以放空,也可以不放空,定义若干个参数。

前3点都是很好懂的,主要是这个第4点了。

在文章开头的程序段中,我在f后面的空格里定义了一个double类型的x作为f的自带参数(当然也可以定义多个,中间用逗号隔开就行了),在main里定义了一个double类型的a,在f里int了一个a(根据变量的作用域,这个a属于不同的域,是不算重复的)。并且,在输入a之后,我让程序输出了f(a)的值。过程如下:

  1. cout检查到要输出f(a)。
  2. 按照填写的先后顺序访问填入f后面的括号中的变量所对应的值,并填入对应的位置(这个过程叫传递参数)。在本例中是访问main中a的值,填入f的括号中,使f的double类型的x等于main的double类型的a,并执行f。
  3. 进入f,定义一个属于f的int类型的a,使这个a等于x。
  4. 使f(x)返回a的值,并且此值重置为int类型。
  5. 返回main,输出f(a)此时的值。

关于第2点,举个例子。比如int f(int x,int y,int z),那么main里如果定义了a,b,c三个变量的话,cout<<f(a,b,c);就是输出当f中的x等于main的a,f中的y等于main的b,f中的z等于main中的c时,f(x,y,z)返回的值。

在上述过程中,第二步所提到的那些值里,在main中填入f函数括号内的,称为“实际参数”;而在传递到f函数,开始执行f函数时,f函数中的x称为“形式参数”。

回到本文的例子,在返回f(x)的值之前,程序中经历了以下3次的数据类型转换:

  1. 获得double类型的待传递参数的值,转换为被传递参数的double类型,并填入被传递参数。
  2. 获得double类型的f里的x的值,转换为int类型的值,并赋值给f里的a。
  3. 因为函数f返回f里a的值,所以获得int类型的f里的a的值,转换为int类型的值,并赋值给整个函数f,然后结束f。
    (如果你这时return 0的话,函数f一定就返回0,那输出也就是0了)

简而言之,在return某个值之前,每个自定义函数都和main一样,可以执行程序语句,不过main以外的其它自定义函数需要被某个正在执行的函数调用就是了。而一旦return某个值,函数就相当于变量,产生一个确定的值,但这个值是一次性的,下次函数再被调用时,依然要重新经过一遍语句的执行来得出一个新的结果。

以上就是函数的自定义了。那么,函数的类型又是什么呢?

有的时候,你自定义一个函数,是为了让它执行一段语句,并不是为了让它返回一个值。这时,函数的类型可以都使用int,结尾都写return 0;也可以令函数的类型为void(英文翻译:虚空,此处用作“空类型”之意),结尾不写return 0;

需要注意的是,void类型只能用于自定义函数,不可用于main函数,更不可用于一般变量/数组等等。且void类型的函数也可以强制退出,即,使用return;语句。此时return后不能写值,应该直接写分号,当void类型函数在执行中遇到return;时即结束。

但是,更多的时候,你是为了让这个自定义函数返回一个值。这时候,函数的类型必须要与你要得到的值相同。如果你想让函数返回一个double类型的值,就必须定义函数为double类型,不可以是float类型,更别说int了。

不过,函数后面的括号里的自带参量的类型,就没有特别要求,依你的需要而定。

那么,又是什么时候要使用自定义函数呢?这就涉及到编程时的一个重要思想:高内聚,低耦合。

高内聚,就是相同或相似功能的语句块尽可能集中在一起。

低耦合,就是功能差异较大的语句块尽可能不要集中在一起。

那么,我们就需要用自定义函数,来表示一个功能。这个把功能实现为自定义函数的过程,叫做“封装”。

这大概可以理解为,你手里有一件事情,这件事可以分解为几个不同的步骤,不同的步骤可以起到不同的效果(功能)。然后你把这几件事分配给另外的人(自定义函数),让他们替你去做。再结合上文的话,你要告诉他具体步骤怎么做,这就是他的函数体;还要告诉他应该用什么东西来做,这就是他的参数。大概就是这样了。

接下来,如何使用自定义函数呢?

在之前的学习中,我们已经使用过诸如pow等数学函数。自定义函数也可以如同数学函数一般调用。如同本文开头的程序段,我们在主函数中输出语句处调用了自定义函数f。自然的,我们也可以在主函数其它区域调用自定义函数。这些地方都属于主函数的函数体。

那么我们可以给出总结:可以在任意函数体内的任意合理位置调用任意函数(主函数除外)。

比如,我们可以在自定义函数中输出helloworld,如下文代码:

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
using namespace std;
void pr()
{
cout<<"helloworld"<<endl;
}
int main()
{
pr();
return 0;
}

在上述代码段中,我们定义了一个自定义函数pr。因为它不需要返回值,所以可以使用void类型;又因为它只是用来输出一个字符串常量,所以不需要参数,因此参数列表为空。

如上,即是自定义函数的使用方法。

第七章到此结束。

--It's the end.Thanks for your read.--