对比不同编程语言中的参数默认值和扩展参数(可变参数)
本文讨论C++、JAVA、C#、EF中参数默认值和扩展参数(可变参数)的实现。只作对比,尽量客观陈述,不作优劣之分,以免引起无谓的语言之争。
如果错误之处,敬请指正。
一、参数默认值
C++:
定义方式:
int
method1(
int
a
=
0
)
int
method2(
int
a ,
int
b
=
0
,
int
c
=
0
)
可以为一个或多个参数指定默认值,第一个具有默认值的参数后面的参数都必须有默认值。 如果在头文件(.h)中指定了参数默认值,对应的定义文件(.cpp)中不能重复指定参数默认值(即使默认值是一致的), 许多人采用这种妥协的方法:int method(int a /* = 0 */) { ... }
调用方式:
x.method1();
//
参数a默认值为0,等效 x.method1(0)
x.method2(
100
);
//
参数b,c均使用默认值0,等效 x.method2(100, 0, 0)
x.method2(
100
,
200
);
//
参数c均使用默认值0,等效 x.method2(100, 200, 0)
//
x.method2(100, , 300);
//
错误,必须给参数b一个值
有一个限制,如果为后面的默认参数未使用默认值,它前面的所有默认参数都不能使用默认值。 因为这个限制,有些程序员在设计方法参数时会倾向于易用性——将使用默认值概率最大的参数放在最后面,概率较小的靠前站,而在一定程序上忽略了参数的逻辑顺序。
Java:
直到Java5才开始支持参数默认值。语法规则与C++一致。因为Java中没有头文件,也就没有了“不能重复指定参数默认值”的限制。 Java5之前只能用方法重载变相实现,参数较多的话可能引起过度重载。比如要实现: int method2(int a , int b = 0, int c = 0) 的效果,要重载以下三个版本:
int
method2(
int
a)
int
method2(
int
a,
int
b)
int
method2(
int
a,
int
b,
int
c)
C#:
目前可能并不支持参数默认值。
EF:
定义方式:
int
method1(
int
a
=
0
)
int
method2(
int
a
=
0
,
int
b,
int
c
=
0
)
与C++规定不同,EF中的每一个参数都可以有默认值,不介意其所在位置。
调用方式:
x.method1();
//
参数a默认值为0,等效 x.method1(0)
x.method2(
100
,
200
);
//
参数c均使用默认值0,等效 x.method2(0, 200, 0)
x.method2(,
200
, );
//
参数a,c均使用默认值0,等效 x.method2(0, 200, 0)
x.method2(,
200
);
//
同上
没有C++的限制,不管参数顺序,都可使用其默认值。
二、扩展参数(可变参数)
C++:
定义方式:
int
method(
int
i, ...)
调用方式:
x.method(
1
); x.method(
1
,
2
); x.method(
1
,
2
,
3
); x.method(
1
,
"
abc
"
,
true
);
参数可以任意扩展,不限制类型和个数。 在方法的实现代码中,无法取得扩展参数的个数和类型。一般做法是像printf一样,让用户明确告知;或者事先约定好。
Java:
定义方式:
int
method(
int
... i)
调用方式:
x.method(
1
); x.method(
1
,
2
); x.method(
1
,
2
,
3
);
编译器会将调用者提供的所有扩展参数组合成一个数组,方法内部可以通过此数组获取各扩展参数的值。
C#:
定义方式:
int
method(
params
int
[] i)
调用方式:
x.method(
1
); x.method(
1
,
2
); x.method(
1
,
2
,
3
);
编译器会将调用者提供的所有扩展参数组合成一个数组,方法内部可以通过此数组获取各扩展参数的值。
EF:
定义方式:
int
method1(extendable
int
i)
int
method2(extendable
int
i, bool b)
//
参数可以“组”为单位进行扩展
调用方式:
x.method1(
1
); x.method1(
1
,
2
); x.method1(
1
,
2
,
3
); x.method2(
1
,
true
);
//
以“组”为单位进行参数扩展
x.method2(
1
,
true
,
2
,
false
); x.method2(
1
,
true
,
2
,
false
,
3
,
false
);
编译器提供某种机制(下一组扩展参数()),可在方法内部可获取各扩展参数的值。
三、总结
在参数默认值和扩展参数(可变参数)方面,Java、C#、EF 都是在继承 C++ 的基础上并有所发展。