默认参数在函数参数较多时是非常有用的.可以只传必须的值,其它取默认值.使用方法如下:
1.默认参数是严格按照从左至右的顺序使用
所以只有如下使用才是合法的
(1)参数全部为默认值. void Fun( int a = 1, int b = 2, int c = 3)
(2)void Fun(int a , int b = 2, int c = 3)
(3)void Fun(int a , int b = 2, int c) //这样是错误的,如果从某处开始使用默认值,则右边所有其他参数也必须有默认值
调用函数的时候传进去的实参个数必须大于或等于无默认值的形参个数.然后匹配参数的时候是从左至右去匹配.不过这样会存在一些问题.
例如
void Fun( int one , int two = 2, int three = 3);
当调用时如果用户想只传两个参数提供one和three的值是做不到的,因为必须从左至右严格匹配,所有要想传值给three,就必须给它前面的所有参数也传值.
自然也有人想到了这问题,于是建议C++之父stroustrup增加一个特性,可以显式指定给第几个参数赋值.比如调用上面函数时可以这样Fun(one = 1 ,three = 3),甚至还可以不按顺序
Fun(three = 3, one = 1)这样用户可以随意指定要赋值给哪个参数,当然没有默认值的参数肯定是要保证都有赋值的.在PL/SQL中的函数调用就完全体现了这种思想.
不过stroustrup觉得这样做带来的好处不是太大,而且有些弊端,于是就没有在C++中添加这特性.比较容易想到的弊端就是由于函数声明和定义中的形参名字是可以不一样的.这样就一来靠形参名字来显式指定传的实参就比较麻烦了.例如声明是void Fun(int one , int two);但定义变成了void Fun(int two, int one) { }
2.参数默认值只能在声明或定义中一处指定.不能同时指定.
例如有类Arwen,然后在头文件中声明函数FunDefault.然后cpp文件中定义.可以用如下两种方式
方法(1)
int FunDefault( int one , int two = 123); //声明
int Arwen::FunDefault(int one , int two) //定义
{
//....
}
方法(2)
int FunDefault( int one , int two );
int Arwen::FunDefault(int one , int two = 123)
{
//....
}
但如下是错误的
方法(3)
int FunDefault( int one , int two = 123 );
int Arwen::FunDefault(int one , int two = 123)
{
//....
}
实际上按道理讲方法(3)是最直观,最易理解的.但可能考虑到一来嘛两个地方都重复赋值下有点麻烦,二来编译器还要去做判断保证两个默认值要一致,所以就干脆不让这样做了.
3.默认参数与函数重载的二义性问题.
假如有函数
void Fun(int one, int two = 2);
void Fun(int one);
当这样调用时Fun(1);上面两个函数都是完全匹配的.所以就有二义性了,编译的时候会报错的.
不过有点奇怪的是只要你是同时有函数声明和定义时才会报错.如果声明和定义是在一起,都在头文件中,也就是内联函数(inline)时,上面这样使用不会报错.Fun(1)调用的是void Fun(int one ,int two = 2); 我是在VS中试的,不知道其他编译器是否做同样的处理
当然了最好我们在代码中避免出现这样的情况.实际上很多时候默认参数就是用来替代函数重载(就像上面的两函数,当一个函数只是比另外一个函数的参数个数多,其他参数相同).所以设计良好的代码应该是没有必要同时存在这样的默认参数与重载函数的