- 7.1 复习函数的基本知识
- 7.1.1 定义函数
- 7.1.2 函数原型和函数调用
- 7.1.2.1 对于函数原型
- 1、为什么需要原型
- 2、原型的语法
- 3、原型的功能
- 7.2 函数参数和按值传递
- 7.2.1 多个参数
本章和第八章介绍如何定义函数、给函数传递消息以及从函数那里获得信息。
本章首先复习函数是如何工作的,然后着重介绍如何使用函数来处理数组、字符串和结构,最后介绍递归和函数指针
7.1 复习函数的基本知识要使用C++函数,必须要完成如下工作:
- 提供函数定义
- 提供函数原型
- 调用函数
创建自己的函数时,必须自行处理3个方面——定义、提供原型和调用。
程序清单7.1演示了这个过程:
#includevoid simple(); int main() { using namespace std; cout << "main() will call the simple() function:n"; simple(); return 0; } void simple() { using namespace std; cout << " I'm but a simple function.n"; }
运行程序如下:
在每个函数定义中,都使用了一条using编译指令,这是因为每个函数都使用了cout。另一种方法是,在函数定义之前放置一条using编译指令或在函数中使用std::cout。
函数可以分为两类:
一类是没有返回值的函数,被称为void函数;
可选的返回语句标记了函数的结尾,否则,函数将在右花括号处结束。
一类是有返回值的函数。必须使用返回语句,以便将值返回给调用函数。值本身可以是常量、变量,也可以是表达式,只是其结果的类型必须是typeName类型或可以转换为double类型。
C++对于返回值有一定的限制: 不能是数组,但可以是其他类型——整数、浮点数、指针,甚至可以是结构和对象!(C++函数不虽然不能直接返回数组,但是可以将数组作为结构或对象组成部分来返回)
7.1.2 函数原型和函数调用 7.1.2.1 对于函数原型首先,需要知道C++需要提供原型的原因。其次,由于C++要求提供原型,因此还应知道正确的语法。最后,应当感谢原型所做的一切。
1、为什么需要原型原型描述了函数到编译器的接口,他将函数返回值的类型以及参数的类型和数量告诉编译器。
... double cube(double x); ... double cube(side);
首先,原型告诉编译器,cube()有一个double参数。如果程序没有提供这样的参数,原型将让编译器能够捕获这种错误。
其次,cube()函数完成计算后,将把返回值放置在指定的位置——可能是CPU寄存器,也可能是内存中。
然后调用函数(这里main())将从这个位置取得返回值。由于原型指出了cube()的类型为double,因此编译器知道应检索多少个字节以及如何解释它们。如果没有这些信息,编译器将只能进行猜测,而编译器是不会这样做的。
为何编译器需要原型,难道它就不能在文件中进一步查找,以了解函数是如何定义的吗?
这种方法的一个问题是效率不高。编译器在搜索文件的剩余部分时将必须停止对main()的编译。
一个更严重的问题是,函数甚至可能并不子啊文件中。C++允许将一个程序放在多个文件中,单独编译这些文件,然后再将它们组合起来。在这种情况下,编译器在编译main() 时,可能无权访问函数代码。如果函数位于库中,情况也是如此。避免使用函数原型的唯一方法是,在首次使用函数之前定义它,但这并不总是可行的。
C++编译的风格是将main()放在最前面,因此它通常提供了程序的整体结构。
2、原型的语法函数原型是一条语句,因此必须以分号结束。
double cube(double x);
获得原型的最简单的方法是,复制函数定义中的函数头,并添加分号。
函数原型不要求提供变量名,有类型列表就足够了。
void cheers(int);
通常,在原型的参数列表中,可以包括变量名,也可以不包括。原型中的变量名相当于占位符,因此不必与函数定义中的变量名相同。
在C++中,不指定参数列表时应使用省略号:
void say_bye(...);
通常,仅当与接受可变参数的C函数(如printf())交互时才需要这样做。
3、原型的功能原型可以极大的降低程序出错的几率:
- 编译器正确处理函数返回值;
- 编译器检查使用的参数数目是否正确;
- 编译器检查使用的参数类型是否正确。如果不正确,则转化为正确的类型(如果可能的话)。
原型自动将被传递的参数强制转换为期望的类型。(但在第8章函数重载可能导致二义性,因此不允许某些自动强制类型转换)
自动类型转换并不能避免所有可能的错误。当较大类型的值被自动转换为较小的类型时,有些编译器将发出警告,指出这可能会丢失数据。
仅当在有意义时,原型化才会导致类型转换。例如,原型不会讲整数转换为结构或指针。
在编译阶段进行的原型化被称为静态类型检查(static type checking)。可以看出,静态类型检查可捕获许多在运行阶段难以捕获的错误。
7.2 函数参数和按值传递C++通常按值传递参数,这意味着将数值参数传递给函数,而后者将其赋给一个新的变量。
用于接受传递值的变量被称为形参。
传递给函数的值被称为实参。
C++标准使用参数(argument)来表示实参,使用参量(parameter)来表示形参,因此参数传递将参量赋给参数。
在函数中声明的变量(包括参数)是该函数私有的。函数调用时,计算机为这些变量分配内存;在函数结束时,计算机将释放这些变量使用的内存。这样的变量被称为局部变量,因此它们被限制在函数中。有助于确保数据的完整性。
在main()中声明一个x变量,同时也在另一个函数中也声明一个名为x的变量,它们完全不同,毫不相关。这样的变量也被称为自动变量,因为它们是在程序执行时自动被分配和释放的。
7.2.1 多个参数原型中的变量名不必与定义中的变量名相同,而且可以省略
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)