本章学习函数相关知识。
采用以下程序段进行说明:
1 |
|
样例输入1:1.1
样例输出1:1
样例输入2:0.9
样例输出2:0
可以看出,我们在公共域(又称全局)里定义了两个函数,一个是int类型的f(自带一个参数,是double类型的x),另一个就是main。
main就不多说了,毕竟int main()是强制要求,不能改动。但是这个f就很有意思了。
首先,我们学到过在公共域直接int f的话表示定义一个int类型的名为f的变量,但现在为什么是个函数呢?那就是因为f后面的小括号了。那么就有以下定义及使用规范四点。
- 满足形如【数据类型 名称(参数列表)】的程序段,就是函数。
- 自定义函数的函数体只能写在公共域或自定义类型内。其中,当自定义函数的函数体写在公共域内时:
- 若自定义函数的函数体写在main函数之前,则可以不在main函数里写其定义语句,因为其函数体那边就已经定义了。
- 若自定义函数的函数体写在main函数之后,则必须在main函数里写其定义语句。总之就是必须满足先定义再使用。
- 只要是函数,就必须使用大括号来告诉程序哪些语句属于这个函数。
- 小括号里可以放空,也可以不放空,定义若干个参数。
前3点都是很好懂的,主要是这个第4点了。
在文章开头的程序段中,我在f后面的空格里定义了一个double类型的x作为f的自带参数(当然也可以定义多个,中间用逗号隔开就行了),在main里定义了一个double类型的a,在f里int了一个a(根据变量的作用域,这个a属于不同的域,是不算重复的)。并且,在输入a之后,我让程序输出了f(a)的值。过程如下:
- cout检查到要输出f(a)。
- 按照填写的先后顺序访问填入f后面的括号中的变量所对应的值,并填入对应的位置(这个过程叫传递参数)。在本例中是访问main中a的值,填入f的括号中,使f的double类型的x等于main的double类型的a,并执行f。
- 进入f,定义一个属于f的int类型的a,使这个a等于x。
- 使f(x)返回a的值,并且此值重置为int类型。
- 返回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次的数据类型转换:
- 获得double类型的待传递参数的值,转换为被传递参数的double类型,并填入被传递参数。
- 获得double类型的f里的x的值,转换为int类型的值,并赋值给f里的a。
- 因为函数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 |
|
在上述代码段中,我们定义了一个自定义函数pr。因为它不需要返回值,所以可以使用void类型;又因为它只是用来输出一个字符串常量,所以不需要参数,因此参数列表为空。
如上,即是自定义函数的使用方法。
第七章到此结束。