(八)程序最小的细胞单元:函数

来源:互联网 发布:高顿网校cpa价格知乎 编辑:程序博客网 时间:2024/05/23 19:46


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 ,子函数结束后仍将存在 。
     









原创粉丝点击