按值传递函数参数
使用const指针参数
指向函数的指针
虽然C++自带了一个大型的函数库,但是编程的真正乐趣在于编写自己的函数。(可以深入学习STL和BOOST 来提高自己的编程效率)
定义函数、给函数传递信息、从函数哪里获取信息。
使用C++函数的步骤:提供函数定义;提供函数原型;调用函数。(在C++的函数库里的函数已经,提供了函数定义和原型,所以可以直接调用函数。但是创建自己的函数时,需要自己实现函数的定义和原型,才能进行函数调用)
例如,在main()函数中调用了一个函数a(),执行程序时,会暂停main()函数中的代码,跳转到a()函数的代码。待a()执行完毕后,再继续执行main()中的代码。
函数可分为两类:void函数——没有返回值的函数 和 有返回值的函数
void函数相当于Pascal中的过程、FORTRAN中的子程序、现代BASIC中的子程序过程。(通常可以使用void函数执行某种操作)
函数定义的语法:类型名 函数名(参数列表){函数体}。(其中参数列表,制定了传递给函数的参数类型和数量)
有返回值的函数,使用return语句返回函数结果。(C++中,return 后可以是 除数组外 的 其他任何数据形式 ,如 常量、变量、表达式、指针、结构、对象、整数、浮点数等,而且它们的类型 必须和 函数的类型名 匹配。虽然C++ 中不能直接返回数组,但是可以将数组作为结构或对象的组成部分来返回)
在底层,函数将 要返回的值 复制到指定的CPU寄存器或内存单元中,之后主程序(主函数)将查看(获取)该内存单元中的值(返回函数 和 主程序 必须就该内存单元中存储的数据类型达成一致——通过提供函数原型告知主程序 该内存的数据类型,并通过函数定义来告诉返回函数 该内存的数据类型。这就解释了为什么要提供函数原型——函数原型虽然看起来和函数定义重复,但它能协助完成函数值的返回。),这样就实现了函数值的返回。
一般将 函数原型 写在(隐藏在) 头文件中(所以,读代码的时候,要把重点放在头文件,这样通过读这些函数的原型,就可以快速了解函数。函数原型描述了函数的接口——这个接口供编译器使用,函数原型将函数的返回值类型、参数类型、参数数量 表达了出来。)
例如,有一个函数原型:double cube(double x)。该原型告诉编译器,cube()有一个double参数(这样如果 程序没有提供这样的参数,编译器就能够捕获这种错误),该原型还告诉编译器 函数的返回值类型是double(这样,当编译器从内存中获取函数的返回值的时候,就知道应该检索对应类型的字节数,来获取内存中的值)。
虽然不提供函数原型,编译器也可以通过在文件中查找函数定义来获取函数信息,但是这种方法效率很低,而且并不总是适用。(首先,编译器搜索文件时,必须停止对main()的编译。其次,当函数定义可能在其他文件时,根本无法在当前文件中搜索到——因为C++允许将一个程序放在多个文件中,每个文件的都是单独编译之后,再进行组合的,所以在编译一个文件的时候是无法访问其他文件代码的。)
避免使用函数原型的唯一方法就是,在调用函数之前定义它。(但是在c++的编程风格就是 将main()函数放在最前面——因为main()函数提供了程序的整体结构。所以C++中需要用到函数原型,这样就可以把除main()函数外的其他函数定义放在main()函数的后面,从而保证main()函数放在最前面)。
函数原型是一条语句(需以;号结尾)。
获取函数原型的方法:直接复制函数定义的函数头,并添加;号。(函数原型的参数列表中的 变量名 可有可无,而且变量名可以是任意的——不一定要和函数定义中的一样。但函数原型的参数列表中的 变量的类型名 是必须的。)
ANSI C借鉴了C++中的函数原型。(二者的区别是,为了和C兼容,ANSI C中的原型 可用可不用。但是 C++中必须使用函数原型)。
C++中 如果不想在原型中指定参数列表,可以使用 ... 号——这意味着将在后面定义参数列表。(一般,仅当与 接受可变参数的C函数交互时才会这么做)。(但是对于 ANSI C,如果不指定参数类表,直接什么都不写就好——就是 ()里面不写东西就行)
函数原型可以帮助编译器完成许多工作,也可以帮助程序员降低程序出错的几率。(当传入函数的参数类型 和 函数中参数类型不一致是,编译器会根据原型提供的信息提示错误或者进行类型的自动转换)。
在编译阶段,编译器根据原型提供的信息来对程序进行检查,被称为 静态类型检查。(静态类型检查可以捕获许多在运行阶段非常难以捕获的错误)