li00020 发表于 2014-8-10 08:57:08

C和C++中的形参默认值

C__带默认值参数的函数说明
1.float area(float r=6.5);
指定r的默认值为6.5,如果在调用此函数时,确认r的值为6.5,则可以不必给出实参的值,如
area( );                              //相当于area(6.5);
如果不想使形参取此默认值,则通过实参另行给出。如area(7.5);                           //形参得到的值为7.5,而不是6.5
这种方法比较灵活,可以简化编程,提高运行效率。
2.如果有多个形参,可以使每个形参有一个默认值,也可以只对一部分形参指定默认值,另一部分形参不指定默认值。
如有一个求圆柱体体积的函数,形参h代表圆柱体的高,r为圆柱体半径。函数原型如下:
float volume(float h,float r=12.5);          //只对形参r指定默认值12.5
函数调用可以采用以下形式:
volume(45.6);                              //相当于volume(45.6,12.5)
volume(34.2,10.4)                            //h的值为34.2,r的值为10.4
3.实参与形参的结合是从左至右顺序进行的。因此指定默认值的参数必须放在形参表列中的最右端,否则出错。
例如:
void f1(float a,int b=0,int c,char d=′a′);   //不正确
void f2(float a,int c,int b=0, char d=′a′);   //正确
如果调用上面的f2函数,可以采取下面的形式:
f2(3.5, 5, 3, ′x′)                  //形参的值全部从实参得到
f2(3.5, 5, 3)                      //最后一个形参的值取默认值′a′
f2(3.5, 5)                         //最后两个形参的值取默认值,b=0,d=′a′
      可以看到,在调用有默认参数的函数时,实参的个数可以与形参的个数不同,实参未给定的,从形参的默认值得到值。利用这一特性,可以使函数的使用更加灵活。例如例4.7求2个数或3个数中的最大数。也可以不用重载函数,而改用带有默认参数的函数。
例4.8 求2个或3个正整数中的最大数,用带有默认参数的函数实现。
#include <iostream>
using namespace std;
int max(int a, int b, int c=0);//函数声明,形参c有默认值
int main( )
{
int a,b,c;
cin>>a>>b>>c;
cout<<″max(a,b,c)=″<<max(a,b,c)<<endl;   //输出3个数中的最大者
cout<<″max(a,b)=″<<max(a,b)<<endl;       //输出2个数中的最大者
return 0;
}
int max(int a,int b,int c)      //函数定义
{
if(b>a) a=b;
if(c>a) a=c;
return a;
}
运行情况如下:
14-56135↙
max(a,b,c)=135
max(a,b)=14
在使用带有默认参数的函数时有两点要注意:
(1) 如果函数的定义在函数调用之前,则应在函数定义中给出默认值。如果函数的定义在函数调用之后,则在函数调用之前需   要有函数声明,此时必须在函数声明中给出默认值,在函数定义时可以不给出默认值(如例4.8)。
(2) 一个函数不能既作为重载函数,又作为有默认参数的函数。因为当调用函数时如果少写一个参数,系统无法判定是利用重载函数      还是利用默认参数的函数,出现二义性,系统无法执行。
(3) 在函数声明和函数定义中,默认参数必须相同。这是错的,因为定义时有实参,但是声明的时候没有实参的话那么定义的时候         的实参没有用,等于没有提供实参!!
C++__带默认值参数的函数说明
          我们可以赋予函数参数默认值。所谓默认值就是在调用时,可以不写某些参数的值,编译器会自动把默认值传递给调用语句中。默认值可以在声明或定义中设置;也可在声明或定义时都设置,都设置时要求默认值是相同的。
关于默认值要注意几点:
(1) .若在定义时而不是在声明时置默认值,那么函数定义一定要在函数的调用之前。因为声明时已经给编译器一个该函数的向导,所      以只在定义时设默认值时,编译器只有检查到定义时才知道函数使用了默认值。若先调用后定义,在调用时编译器并不知道哪个      参数设了默认值。所以我们通常是将默认值的设置放在声明中而不是定义中。
(2) .不能将实际值传递给引用类型的参数。可以将变量作引用类型参数的默认值,这时变量必须是已经声明且是全局变量。
      声明函数时,要将类或结构中定义 的静态成员变量作为默认值,若该类或结构还未创建实例,那要在此静态成员变量前加上作用       域操作符(::)。
   若已声明了类或结构的实例,则引用其成员变量作为函数参数的默认值,就要在变量前加上实例名和成员操作符(.)。
(3) .若给某一参数设置了默认值,那么在参数表中其后所有的参数都必须也设置默认值,否则,由于函数调用时可不列出已设置默认       值的参数,编译器无法判断在调用时是否有参数遗漏。(实参和形参是从左向右结合的)
(4) .在调用时,若给已经设置默认值的参数传递实际值,既要取代默认值,则在参数表中被取代参数的左边所定义的所有参数,无论       是否有默认值,都必须传递实际参数。
      这也是因为函数调用时可不列出已设置默认值的参数。假若被取代参数的左边既有设置了默认值的参数也有未设置默认值的参         数,若不对其左边的所有参数传递实际参数,编译器也就无法分辨传递的这个取代值到底要传递给哪个参数。
例如有以下函数声明:
int FunctionOne(int x,int y=0,int z=0,int w=0);
我们要给z 传递整型值8,作如下调用:
FunctionOne(8);
显然,编译器无法确定这个8 到底要传递给哪个参数。为了达到我们的目的,必须这样调用:
FunctionOne(0,0,8);
这是x 被传递了0,y 被传递了 0,z 被传递了8

*******************************************************************************************
第九节 默认参数的函数
1.默认参数的目的
  C++可以给函数定义默认参数值。通常,调用函数时,要为函数的每个参数给定对应的实参。例如:
    void delay(int loops); //函数声明
    void delay(int loops) //函数定义
    {
     if(100ps==0)
      return;
      for(int i=0;i<loops,i++);
    }
  无论何时调用delay()函数,都必须给loops传一个值以确定时间。但有时需要用相同的实参反复调用delay()函数。C++可以给参数定义默认值。如果将delay( )函数中的loops定义成默认值1000, 只需简单地把函数声明改为:
    void delay(int loops=1000);
  这样,无论何时调用delay()函数,都不用给loops赋值,程序会自动将它当作值1000进行处理。例如,调用:
    delay(2500); //loops设置为2500
    delay(); //ok:loops采用默认值1000
  调用中,若不给出参数,则按指定的默认值进行工作。
  允许函数默认参数值,是为了让编程简单,让编译器做更多的检查错误工作。

2.默认参数的声明
  默认参数在函数声明中提供,当又有声明又有定义时,定义中不允许默认参数。如果函数只有定义,则默认参数才可出现在函数定义中。例如:
    void point(int=3,int=4); //声明中给出默认值
    void point(intx,inty) //定义中不允许再给出默认值
    {
     cout <<x<<endl;
     cout <<y<<endl;
    }

3.默认参数的顺序规定

  如果一个函数中有多个默认参数,则形参分布中,默认参数应从右至左逐渐定义。当调用函数时,只能向左匹配参数。例如:
    void func(int a=1,int b,int c=3, int d=4); //error
    void func(int a, int b=2,int c=3,int d=4); //ok
  对于第2个函数声明,其调用的方法规定为:
    func(10,15,20,30); //ok:调用时给出所有实参
    func(); //error:参数a没有默认值
    func(2,12); //ok:参数c和d默认
    func(2,15,20); //error:只能从右到左顺序匹配默认 (这好像有异议)

4.默认参数与函数重载

  默认参数可将一系列简单的重载函数合成为一个。例如, 下面3个重载函数:
    void point(int,int){//...}
    void point(int a){return point(a,4);}
    void point(){return point(3,4);}
  可以用下面的默认参数的函数来替代:
    void point(int=3,int=4);
  当调用“point();”时,即调用“point(3,4);” 它是第3个声明的重载函数。
  当调用“point(6);”时,即调用“point(6,4);”,它是第2个声明的重载函数。
  当调用“point(7,8);”时,即调用第1个声明的重载函数
  如果一组重载函数(可能带有默认参数)都允许相同实參个数的调用,将会引起调用的二义性。例如:
    void func(int); //重载函数之一
    void func(int,int=4); //重载函数之二,带有默认参数
    void func(int=3,int=4); //重载函数之三,带有默认参数
    func(7); //error: 到底调用3个重载函数中的哪个?
    func(20,30) //error:到底调用后面2个重载函数的哪个?

5.默认值的限定

  默认值可以是全局变量、全局常量,甚至是一个函数。例如:
    int a=1;
    int fun(int);
    int g(int x;fun(a)); //ok:允许默认值为函数
  默认值不可以是局部变量,因为默认参数的函数调用是在编译时确定的,而局部变量的位置与值在编译时均无法确定。例如:
    void fun()
    {
     int i;
     void g(int x=i); //error:处理g()函数声明时,i不可见
    }
本章小结

  随着程序量和程序复杂度的不断增加,最好的办法是把程序分成更小,更容易管理的模块,这种模块就是函数。
  函数名最好能反映出所要完成的任务。
  函数可以把数据返回给调用者,若函数要返回一个值,必须在函数名前规定返回值的类型,若函数没有返回值,则类型为void。
  程序通过参数把信息传递给函数,若函数需要接受参数,就必须给参数指定名称及类型。
  C++必须知道函数的返回类型以及接受的参数个数和类型, 如果函数的定义出现在函数调用之后,就必须在程序的开始部分用函数原型进行声明。
  局部变量是在函数内部定义的,只能被定义该变量的函数访问。全局变量是指其作用域贯穿程序始终的变量。定义全局变量要在程序开始时进行,并且放在所有函数的外面。
  静态局部变量是在函数内部定义,但生命期却随函数的第一次被调用而产生, 随程序的结束而结束, 静态局部变量只能在定义该变量的函数中可见。
  函数调用机制是由栈操作的过程实现的。函数可以递归调用。函数定义不能放在任何函数定义的里面。
  内联函数是为了提高编程效率而实现的, 它克服了用#define宏定义所带来的弊病。
  函数重载允许用同一个函数名定义多个函数。连接程序会根据传递给函数的参数数目、类型和顺序调用相应的函数。函数重载使程序设计简单化,程序员只要记住一个函数名,就可以完成一系列相关的任务。
  在函数定义中通过赋值运算,即可指定默认参数值。一旦程序在调用函数时默认了参数值, 函数就使用默认参数值。 不允许在参数中间使用默认值。指定默认参数值可以使函数的使用更为简单,同时也增强了函数的可重用性。
页: [1]
查看完整版本: C和C++中的形参默认值