1、函数名与形参列表合称"函数签名“
编译器根据函数签名来确定调用哪个函数。因此尽管函数名相同,但形参不同,但编译器总能准确定位调用了哪个函数。
因此,一个程序中有两个函数,其函数名、形参都相同,但返回值不同。编译器就不会区别这两个函数,总认为第二为重定义,就会出错。
2、函数的返回值,其值在函数结束时会消失,但其副本会返回到函数调用处。
对于void返回类型的函数,返回只须return; 就OK啦。
注意:函数体最后的右花括号,当程序执行到此处时,这个右花括号相当于”return;",因此在返回值为void,即使没有显式的return;也不会出错,
但是若是有返回值而无return则会出错。
3、函数声明后才能使用函数。函数声明时,只须声明其类型即可,包括其形参。(为了标准化书写,我们一般都应该写全,这样易于阅读)
double sum(double,double); //这也是正确的声明,只须说明类型即可。
因此对于传送数组时,可以不带其上限值。如
double sum(double a[ ],double b); //这是正确的,勿须带数值。
double sum(double a[4],double b); // 这也是正确的,带上数值不改变它的“类型”
double sum(double *p,double b); //这还是正确的,因为它的类型是一致的。
更深一步,因为数组的数组名可替换指针,但它是const类型,因此,上面最后一个可以改变P值,可以稍微强化一下:
double sum(double *const p,double b); //表明p是常量,是不能更改的,但原数组时的数据可以更换如 *p=34;
double sum(const double* p; double b);//表明p是变量,但所指的原数组里数据应当作“常量”来看,不应更改 原数组里的数据。
再细一步,由于函数始终用的是副本,把传过来的副本当const一般是没有很大的意义,只是为了区别阅读。但副本所指的数据变化就有重大的意义了。
4、重点:引用
一、定义:
引用:就是一个变量的别名。就如同人一样还有除了大名(变量),还有小名(别名)。
一个变量可以有几个引用,也就是有几个别名。比如父母叫你“张文”,小时候村上人称你为“狗剩”,工作后同事叫你“文兄“(文胸),反正都是你。
int a=3;
int& b=a;
int& c=a;//第二个别名
引用,在定义时就必须初始化,指定是哪个的别名。
与指针的区别:引用在很多时候象指针,但它可以直接使用引用来替代原变量,但指针不行,须解除指针,如*p=3
另外一个就是指针可以置空,p=0, 但引用不行(根据必须初始化原则),它必须是一个确定的有的变量(这个变量是存在的)。
二、函数调用时使用引用。
前面不管是使用数值还是指针,都是值传递,都会传递给函数副本。
但引用不会,它直接连副本传递都省略了,直接使用原值。(因此,高效的同时也带了修改原值的风险)
因为引用和被引用的变量,两者是等价的。
double sum(double& a,double b);// 这里a就是原变量的引用(别名),不是副本。
根据定义,引用是”变量“的别名,因此,如果调用函数中不是变量,而用别名,会出错。如:实参是常量就会发生”类型“不一致。故对于常量就应:
double sum(double& a,const double& b);// 注意这里a是调用处变量的别名,而b则是原调用处的常量。
sum(c,3.2); //原调用处。
5、主函数带参情况:
int main(int argc, char *argv[])
可以看到主函数带两个参数。主要为命令方式时后面带参数服务。
参数1:argc 表明带有几个字串,其指针在后面参数的数组中。
参数2:argv[ ] 一个指针数组。其指针的个数是argc+1,因为最后一个指针必须是0,所以加上了1.第一个指针一定是指向程序名本身的字串。
例:dir /w 这是DOS命令中列出文件,按列表方式列出
其中argc=2 ,因为有两个字串,须两个指针。即第一个字串为程序本身字串:dir,第二个字串为“/w"
argv[ ] 指针数组有三个元素(指针),除了前面两个字串的地址(指针)外,还有最后一个元素(指针)为0
6、函数的默认值。
可以在函数声明中,直接用=给形参赋值,表示这个形参的“默认值”。
重要原则:默认值的形参只能从右边开始排列,且调用时省略也是从右边逐渐省略,不能跳跃省略。
例:假定声明函数有5个形参,其中后(右边)三个为有默认值的。那么调用时:
省略一个参数情况:只能是第5个。
省略两个参数情况:只能是第4、5个,不能是第3、5个(这是跳跃了,只能从右逐渐向左)
活力参个参数情况:只能是第3、4、5个。
7、返回值是指针和引用时注意: 不要返回是函数中局部变量的指针或指针。
因为一离开函数,其作用域就失效了,其指针和引用就失效了,就容易出错。
例主函数中: *larger(a,b)=100; //原义是,返回最大值的指针并将最大值改为100
子函数: int* larger(int a,int b)
{ if (a>b) return &a;
if(b>a) return &b;
}
上面会出错,因为a、b为副本,返回副本的地址,但一离开函数,其变量就消亡了。
改为 int* larger(int& a, int&b )就正确了,因为是引用,就是主函数的东西。作用域不会失效。
特别注意的是,在子函数中new的内存,若不在子函数中delete ,子函数结束后仍将存在 。