在手头的某本C++教材里,有关本节内容的第一句话是:“参数默认值也称默认参数值”。对着这话我愣了半天才算明白。所以在后面课程里,有些地方我说“参数默认值”有些地方我又会胡里胡涂说成“默认参数值”。你可不别像我一样去“研究”二者的区别呵。个人认为,从词法角度上看,“参数默认值”更准确些。
C++支持在定义或声明函数时,设置某些参数的默认值,这一点C不允许。
比如我们为卖萝卜的大娘的写一个计价函数。这个函数需要三个参数:顾客交多钱?买多少斤萝卜?及萝卜的单价。返回值则是大娘应该找多少钱。例如,顾客交了100元,他买5斤萝卜,单价是1.00元/斤。那么函数就会计算并返回95,表示应该找给顾客95元钱。
//函数定义如下:
float GiveChange(float money, float count, float price)
{
return money - count * price; //找钱 = 已付款 - 数量 * 单价
}
当我们在程序中需要使用该函数时,我们大致是这样调用:
float change = GiveChange(100,5,1);
看上去一切很完美--确实也很完美。不过C++允许我们锦上添花。并且不是一朵只为了好看的“花”。
现实情况是,萝卜的价钱是一个比较稳定的数--当然并不是不会变,在时出现亚洲经济风暴,萝卜价还是发变--总之是会变,但很少变。
碰上这种情况,我们每回在调用函数时都写上最后一个参数,就有些亏了,这时,我们可以使用“参数的默认值”。
//首先,函数的定义做一点改动:
float GiveChage(float money, float count, float price = 1.0)
{
.....
}
看到变化了吗?并不是指函数体内我打了省略号,而是在函数参数列表中,最后一个参数的定义变为:float price = 1.0。这就默认参数值,我们指定价格默认为1元。
然后如何使用呢?
以后在代码中,当需要计算找钱时,如果价钱没有变,我们就可以这样调用:
float change = GiveChange(100,5); //没有传递最后一个参数。
是的,我没有写最后一参数:价钱是多少?但编译器发现这一点时,会自动为我填上默认的1.0。
如果在代码的个别地方,大娘想改一改价钱,比如某天笔者成了顾客,大娘决定按1斤2毛钱把萝卜卖给我:
我给大娘5毛钱,买2斤:
float changeForBCBSchool = GiveChange(0.5, 2 ,0.2); //你一样可以继续带参数
我想,这个实例很直观,但必须承认这个例子并没有体现出参数默认值的种种优点。不过不管如何,你现在应该对参数的默认值有感性认识。
下面学习有关参数默认值的具体规定。
1、必须从最右边开始,然后连续地设置默认值。
如果理解这句话?
首先我们看关键词“最右边”。也就是说假如一个函数有多个参数,那么你必须从最后一个参数开始设置默认值。
如:
void foo(int a, int b, bool c);
那么,下面的设置是正确的:
void foo(int a, int b, bool c = false); //ok,c是最后一个参数
//而,下面是错误的:
void foo(int a, int b = 0, bool c); //fail,b不是最后一参数
然后我们看“连续”。也就是说,从最右边开始,你可以连续地向左设置多个参数的默认值,而不能跳过其中几个:
如:
下面的的设置是正确的:
void foo(int a, int b=0, bool c = false); //ok ,连续地设置c,b的默认值
同样,这也是正确的:
void foo(int a=100, int b=0, bool c = false); //ok ,连续地设置c,b,a的默认值
//而,这样设置是错误的:
void foo(int a=100, int b, bool c = false); //fale,不行,你不能跳过中间的b。
2、如果在函数的声明里设置了参数默认值,那么就不参在函数的定义中再次设置默认值。
函数的“声明”和“定义”你可能又有些胡涂了。好,就趁此再复习一次。
所谓的“定义”,也称为“实现”,它是函数完整的代码,如:
//函数定义如下(函数定义也称函数的实现):
float GiveChange(float money, float count, float price)
{
return money - count * price; //找钱 = 已付款 - 数量 * 单价
}
而函数的“声明”,则是我们上一章不断在说的函数的“名片”,它用于列出函数的格式,函数的声明包含函数的“返回类型,函数名,参数列表”,惟一和函数定义不一样的,就是它没有实现部分,而是直接以一分号结束,如:
//声明一个函数:
float GiveChange(float money, float count, float price); //<---注意,直接以分号结束。
现在和参数默认值有关的是,如果你在函数声明里设置了默认值,那就不用,也不能在函数定义处再设置一次。
如,下面代码正确:
----------------------------------------
//定义:
float GiveChange(float money, float count, float price)
{
return money - count * price; //找钱 = 已付款 - 数量 * 单价
}
//声明:
float GiveChange(float money, float count, float price = 1.0);
----------------------------------------
而下面的代码有误:
//定义:
float GiveChange(float money, float count, float price = 1.0)
{
return money - count * price; //找钱 = 已付款 - 数量 * 单价
}
//声明:
float GiveChange(float money, float count, float price = 1.0);
----------------------------------------
3、默认值可以最常见的常数,或全局变量,全局常量,甚至可以是一个函数的调用。
关于题中的“全局”,我们还没有学习,这时理解就是在程序运行区别稳定存在的变量或常量。下面举一个让我们比较狐疑的,使用函数作来参数默认的例子:
//某个返回double的函数:
double func1();
double func2(double a, double b = func1()); //func1()的执行结果将被用做b的默认值。